From 43a9de08a056bf0968876aca81e5cf3c3a73e4f3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 14:14:58 +0100 Subject: [PATCH 01/71] Add SWCommand Add SWCommandUtils Add InternalCommand Add InternalTabComplete --- .../de/steamwar/command/InternalCommand.java | 54 ++++++++ .../steamwar/command/InternalTabComplete.java | 53 +++++++ .../src/de/steamwar/command/SWCommand.java | 102 ++++++++++++++ .../de/steamwar/command/SWCommandUtils.java | 130 ++++++++++++++++++ 4 files changed, 339 insertions(+) create mode 100644 SpigotCore_Main/src/de/steamwar/command/InternalCommand.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/SWCommand.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java new file mode 100644 index 0000000..bf0d759 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java @@ -0,0 +1,54 @@ +/* + * 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 InternalCommand { + + private SWCommand swCommand; + private Method method; + private Parameter[] parameters; + + InternalCommand(SWCommand swCommand, Method method) { + this.swCommand = swCommand; + this.method = method; + parameters = method.getParameters(); + } + + boolean invoke(CommandSender commandSender, String[] args) { + if (args.length < parameters.length - 1) return false; + Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, parameters, args); + try { + method.setAccessible(true); + method.invoke(swCommand, objects); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new SecurityException(e.getMessage(), e); + } catch (InvocationTargetException e) { + return false; + } + return true; + } + +} diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java b/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java new file mode 100644 index 0000000..b6f0d47 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java @@ -0,0 +1,53 @@ +/* + * 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; + Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, parameters, args); + try { + 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 new file mode 100644 index 0000000..725b891 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -0,0 +1,102 @@ +/* + * 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.Command; +import org.bukkit.command.CommandSender; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.*; +import java.util.function.Consumer; + +public abstract class SWCommand { + + private final Set commandSet = new HashSet<>(); + private final Set tabCompleteSet = new HashSet<>(); + private Consumer helpMessage = sender -> {}; + + protected SWCommand(String command, String... aliases) { + 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)) { + return false; + } + } + return false; + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + List strings = new ArrayList<>(); + for (InternalTabComplete internalTabComplete : tabCompleteSet) { + SWCommandUtils.TabComplete tabComplete = internalTabComplete.invoke(sender, args); + if (tabComplete != null) { + strings.addAll(tabComplete.tabCompletes); + } + } + return strings; + } + }); + } + + protected final void register(String methodName) { + if (methodName.equals("onCommand")) return; + if (methodName.equals("onTabComplete")) return; + Method[] methods = this.getClass().getDeclaredMethods(); + for (Method method : methods) { + 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)); + } + } + } + + private boolean validMethod(Method method) { + Parameter[] parameters = method.getParameters(); + if (parameters.length == 0) return false; + if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) return false; + 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(); + } + if (clazz.isEnum()) continue; + if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz)) return false; + } + return true; + } + + protected final void setHelpMessage(Consumer helpMessage) { + assert helpMessage != null; + this.helpMessage = helpMessage; + } + + protected final void sendHelpMessage(T sender) { + helpMessage.accept(sender); + } + +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java new file mode 100644 index 0000000..aaa194e --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -0,0 +1,130 @@ +/* + * 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.Bukkit; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.lang.reflect.Parameter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.BiFunction; +import java.util.function.Function; + +class SWCommandUtils { + + private SWCommandUtils() { + throw new IllegalStateException("Utility Class"); + } + + static final Map, Function> MAPPER_FUNCTIONS = new HashMap<>(); + + static final Function ERROR_FUNCTION = s -> { + throw new SecurityException(s); + }; + + static final BiFunction>, String, Enum> ENUM_MAPPER = (enumClass, s) -> { + Enum[] enums = enumClass.getEnumConstants(); + for (Enum e : enums) { + if (e.name().equals(s)) return e; + } + return null; + }; + + static { + MAPPER_FUNCTIONS.put(boolean.class, Boolean::parseBoolean); + MAPPER_FUNCTIONS.put(Boolean.class, Boolean::parseBoolean); + MAPPER_FUNCTIONS.put(float.class, Float::parseFloat); + MAPPER_FUNCTIONS.put(Float.class, Float::parseFloat); + MAPPER_FUNCTIONS.put(double.class, Double::parseDouble); + MAPPER_FUNCTIONS.put(Double.class, Double::parseDouble); + MAPPER_FUNCTIONS.put(int.class, Integer::parseInt); + MAPPER_FUNCTIONS.put(Integer.class, Integer::parseInt); + MAPPER_FUNCTIONS.put(String.class, s -> s); + MAPPER_FUNCTIONS.put(StringBuilder.class, StringBuilder::new); + MAPPER_FUNCTIONS.put(Player.class, Bukkit::getPlayer); + MAPPER_FUNCTIONS.put(UUID.class, UUID::fromString); + } + + static final CommandMap commandMap; + + static { + try { + final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + commandMapField.setAccessible(true); + commandMap = (CommandMap) commandMapField.get(Bukkit.getServer()); + } catch (NoSuchFieldException | IllegalAccessException exception) { + Bukkit.shutdown(); + throw new SecurityException("Oh shit. Commands cannot be register.", exception); + } + } + + public static Object[] generateArgumentArray(CommandSender commandSender, 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); + + for (int i = 1; i < parameters.length - (varArgs ? 1 : 0); i++) { + Class clazz = parameters[i].getType(); + arguments[i] = mapper(clazz).apply(args[i - 1]); + } + + if (varArgs) { + Object[] varArgument = new Object[args.length - parameters.length + 2]; + arguments[arguments.length - 1] = varArgument; + Function mapper = mapper(parameters[parameters.length - 1].getType().getComponentType()); + + int index = 0; + for (int i = parameters.length - 2; i < args.length; i++) { + varArgument[index++] = mapper.apply(args[i]); + } + } + + return arguments; + } + + @SuppressWarnings("unchecked") + private static Function mapper(Class clazz) { + if (clazz.isEnum()) { + Class> enumClass = (Class>) clazz; + return s -> ENUM_MAPPER.apply(enumClass, s); + } else { + return s -> MAPPER_FUNCTIONS.getOrDefault(clazz, ERROR_FUNCTION).apply(s); + } + } + + public static class TabComplete { + final List tabCompletes; + + public TabComplete(List tabCompletes) { + this.tabCompletes = tabCompletes; + } + } + +} From b3c4c45892340a42815095529f97e333d523fa97 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 15:52:46 +0100 Subject: [PATCH 02/71] Add StringConstraint for subCommand definitions --- .../src/de/steamwar/command/SWCommand.java | 2 ++ .../de/steamwar/command/SWCommandUtils.java | 10 +++--- .../de/steamwar/command/StringConstraint.java | 31 +++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/command/StringConstraint.java diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 725b891..5c31b83 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -80,7 +80,9 @@ public abstract class SWCommand { if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) return false; for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; + StringConstraint stringConstraint = parameter.getAnnotation(StringConstraint.class); Class clazz = parameter.getType(); + if (stringConstraint != null && clazz != String.class) return false; if (parameter.isVarArgs() && i == parameters.length - 1) { clazz = parameter.getType().getComponentType(); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index aaa194e..c225205 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -26,10 +26,7 @@ import org.bukkit.entity.Player; import java.lang.reflect.Field; import java.lang.reflect.Parameter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; @@ -91,8 +88,13 @@ class SWCommandUtils { arguments[0] = parameters[0].getType().cast(commandSender); for (int i = 1; i < parameters.length - (varArgs ? 1 : 0); i++) { + Parameter parameter = parameters[i]; Class clazz = parameters[i].getType(); arguments[i] = mapper(clazz).apply(args[i - 1]); + StringConstraint stringConstraint = parameter.getAnnotation(StringConstraint.class); + if (stringConstraint != null && !Objects.equals(arguments[i], stringConstraint.constraint())) { + throw new SecurityException(); + } } if (varArgs) { diff --git a/SpigotCore_Main/src/de/steamwar/command/StringConstraint.java b/SpigotCore_Main/src/de/steamwar/command/StringConstraint.java new file mode 100644 index 0000000..368ad18 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/StringConstraint.java @@ -0,0 +1,31 @@ +/* + * 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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER}) +public @interface StringConstraint { + String constraint(); +} From ce7d261174c8d5d6b2ce45126cb35b6507786643 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 16:30:40 +0100 Subject: [PATCH 03/71] Remove SWCommand.register method Add SWCommand.Register annotation --- .../src/de/steamwar/command/SWCommand.java | 24 +++++++++----- .../de/steamwar/command/SWCommandUtils.java | 2 +- .../de/steamwar/command/StringConstraint.java | 31 ------------------- 3 files changed, 18 insertions(+), 39 deletions(-) delete mode 100644 SpigotCore_Main/src/de/steamwar/command/StringConstraint.java diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 5c31b83..d871838 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -22,6 +22,10 @@ package de.steamwar.command; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; @@ -57,14 +61,9 @@ public abstract class SWCommand { return strings; } }); - } - protected final void register(String methodName) { - if (methodName.equals("onCommand")) return; - if (methodName.equals("onTabComplete")) return; - Method[] methods = this.getClass().getDeclaredMethods(); - for (Method method : methods) { - if (!validMethod(method)) continue; + for (Method method : getClass().getDeclaredMethods()) { + if (method.getDeclaredAnnotation(Register.class) == null || !validMethod(method)) continue; if (method.getReturnType() == Void.TYPE) { commandSet.add(new InternalCommand(this, method)); } @@ -101,4 +100,15 @@ public abstract class SWCommand { helpMessage.accept(sender); } + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + protected @interface Register { + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.PARAMETER}) + @interface StringConstraint { + String constraint(); + } + } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index c225205..6434dc8 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -91,7 +91,7 @@ class SWCommandUtils { Parameter parameter = parameters[i]; Class clazz = parameters[i].getType(); arguments[i] = mapper(clazz).apply(args[i - 1]); - StringConstraint stringConstraint = parameter.getAnnotation(StringConstraint.class); + SWCommand.StringConstraint stringConstraint = parameter.getAnnotation(SWCommand.StringConstraint.class); if (stringConstraint != null && !Objects.equals(arguments[i], stringConstraint.constraint())) { throw new SecurityException(); } diff --git a/SpigotCore_Main/src/de/steamwar/command/StringConstraint.java b/SpigotCore_Main/src/de/steamwar/command/StringConstraint.java deleted file mode 100644 index 368ad18..0000000 --- a/SpigotCore_Main/src/de/steamwar/command/StringConstraint.java +++ /dev/null @@ -1,31 +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 java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.PARAMETER}) -public @interface StringConstraint { - String constraint(); -} From 03d35042e3f0ca7d9f655be20c4c0ea301195d34 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 17:06:37 +0100 Subject: [PATCH 04/71] Remove SWCommand.StringConstraints Add SWCommand.Register.subCommand --- .../src/de/steamwar/command/SWCommand.java | 9 +-------- .../src/de/steamwar/command/SWCommandUtils.java | 16 +++++++++------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index d871838..4176c7a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -79,9 +79,7 @@ public abstract class SWCommand { if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) return false; for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; - StringConstraint stringConstraint = parameter.getAnnotation(StringConstraint.class); Class clazz = parameter.getType(); - if (stringConstraint != null && clazz != String.class) return false; if (parameter.isVarArgs() && i == parameters.length - 1) { clazz = parameter.getType().getComponentType(); } @@ -103,12 +101,7 @@ public abstract class SWCommand { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) protected @interface Register { - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.PARAMETER}) - @interface StringConstraint { - String constraint(); + String[] subCommand() default {}; } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 6434dc8..3c33705 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -25,6 +25,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; import java.util.function.BiFunction; @@ -78,7 +79,7 @@ class SWCommandUtils { } } - public static Object[] generateArgumentArray(CommandSender commandSender, Parameter[] parameters, String[] args) { + 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()) { @@ -87,14 +88,15 @@ class SWCommandUtils { } arguments[0] = parameters[0].getType().cast(commandSender); - for (int i = 1; i < parameters.length - (varArgs ? 1 : 0); i++) { - Parameter parameter = parameters[i]; + SWCommand.Register register = method.getAnnotation(SWCommand.Register.class); + int subCommandIndex = 1; + for (String s : register.subCommand()) { + if (!args[subCommandIndex++].equals(s)) throw new SecurityException(); + } + + for (int i = subCommandIndex; i < parameters.length - (varArgs ? 1 : 0); i++) { Class clazz = parameters[i].getType(); arguments[i] = mapper(clazz).apply(args[i - 1]); - SWCommand.StringConstraint stringConstraint = parameter.getAnnotation(SWCommand.StringConstraint.class); - if (stringConstraint != null && !Objects.equals(arguments[i], stringConstraint.constraint())) { - throw new SecurityException(); - } } if (varArgs) { From bba1c1fbf7b5e9444863d6362e09deddc48339ec Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 17:10:24 +0100 Subject: [PATCH 05/71] Fix SWCommand --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 4176c7a..14522e1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -63,7 +63,8 @@ public abstract class SWCommand { }); for (Method method : getClass().getDeclaredMethods()) { - if (method.getDeclaredAnnotation(Register.class) == null || !validMethod(method)) continue; + if (method.getDeclaredAnnotation(Register.class) == null) continue; + if (!validMethod(method)) continue; if (method.getReturnType() == Void.TYPE) { commandSet.add(new InternalCommand(this, method)); } From a4d0f528f8e66e22a2a204ab7dba0afe15ef1660 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 17:24:18 +0100 Subject: [PATCH 06/71] Fix InternalCommand Fix InternalTabComplete --- SpigotCore_Main/src/de/steamwar/command/InternalCommand.java | 2 +- .../src/de/steamwar/command/InternalTabComplete.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java index bf0d759..5595992 100644 --- a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java @@ -39,8 +39,8 @@ class InternalCommand { boolean invoke(CommandSender commandSender, String[] args) { if (args.length < parameters.length - 1) return false; - Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, parameters, args); try { + Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, method, parameters, args); method.setAccessible(true); method.invoke(swCommand, objects); } catch (IllegalArgumentException | IllegalAccessException e) { diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java b/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java index b6f0d47..44effb6 100644 --- a/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java +++ b/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java @@ -39,8 +39,8 @@ class InternalTabComplete { SWCommandUtils.TabComplete invoke(CommandSender commandSender, String[] args) { if (args.length < parameters.length - 1) return null; - Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, parameters, args); try { + Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, method, parameters, args); method.setAccessible(true); return (SWCommandUtils.TabComplete) method.invoke(swCommand, objects); } catch (IllegalArgumentException | IllegalAccessException e) { From 3d5ae1986359e60357b768ff643d59ac650a955f Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 17:26:39 +0100 Subject: [PATCH 07/71] Add SWCommandUtils.addMapper --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 3c33705..87d77d5 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -131,4 +131,9 @@ class SWCommandUtils { } } + public static void addMapper(Class clazz, Function mapper) { + if (MAPPER_FUNCTIONS.containsKey(clazz)) return; + MAPPER_FUNCTIONS.put(clazz, mapper); + } + } From 67b7f431e0de387dce3a86cef8cdc097116c2384 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 17:38:26 +0100 Subject: [PATCH 08/71] Simplify SWCommand Constructor --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 14522e1..52b8da1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -37,6 +37,10 @@ public abstract class SWCommand { private final Set tabCompleteSet = new HashSet<>(); private Consumer helpMessage = sender -> {}; + protected SWCommand(String command) { + this(command, new String[0]); + } + protected SWCommand(String command, String... aliases) { SWCommandUtils.commandMap.register("steamwar", new Command(command, "", "/" + command, Arrays.asList(aliases)) { @Override From 9d149169400c8eb69bf00e47164cfa50c4938166 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 17:48:41 +0100 Subject: [PATCH 09/71] Fix SWCommandUtils.commandMap --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 87d77d5..09e1436 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -75,7 +75,7 @@ class SWCommandUtils { commandMap = (CommandMap) commandMapField.get(Bukkit.getServer()); } catch (NoSuchFieldException | IllegalAccessException exception) { Bukkit.shutdown(); - throw new SecurityException("Oh shit. Commands cannot be register.", exception); + throw new SecurityException("Oh shit. Commands cannot be registered.", exception); } } From 811bc921a4c6057d411407e8161dec1dcdcbea44 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 12 Mar 2021 18:12:07 +0100 Subject: [PATCH 10/71] Add SWCommand.subCommandTabCompletes --- .../src/de/steamwar/command/SWCommand.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 52b8da1..dbd5a66 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -35,6 +35,7 @@ public abstract class SWCommand { private final Set commandSet = new HashSet<>(); private final Set tabCompleteSet = new HashSet<>(); + private final Map> subCommandTabCompletes = new HashMap<>(); private Consumer helpMessage = sender -> {}; protected SWCommand(String command) { @@ -55,19 +56,30 @@ public abstract class SWCommand { @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { - List strings = new ArrayList<>(); + 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); } } + strings = new ArrayList<>(strings); + for (int i = strings.size() - 1; i >= 0; i--) { + if (!strings.get(i).startsWith(args[args.length - 1])) { + strings.remove(i); + } + } return strings; } }); for (Method method : getClass().getDeclaredMethods()) { - if (method.getDeclaredAnnotation(Register.class) == null) continue; + Register register = method.getDeclaredAnnotation(Register.class); + 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)); From d028b27ec5940a697cde64e5767595eaf5d5fca9 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 13 Mar 2021 15:58:56 +0100 Subject: [PATCH 11/71] Add TypeMapper --- .../src/de/steamwar/command/SWCommand.java | 2 + .../de/steamwar/command/SWCommandUtils.java | 182 ++++++++++++++++-- .../src/de/steamwar/command/TypeMapper.java | 29 +++ 3 files changed, 196 insertions(+), 17 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/command/TypeMapper.java diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index dbd5a66..350d574 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -51,11 +51,13 @@ public abstract class SWCommand { return false; } } + helpMessage.accept(sender); return false; } @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + // TODO: add better tab complete, command based List strings = new ArrayList<>(subCommandTabCompletes.getOrDefault(args.length, new HashSet<>())); for (InternalTabComplete internalTabComplete : tabCompleteSet) { SWCommandUtils.TabComplete tabComplete = internalTabComplete.invoke(sender, args); diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 09e1436..de7c1d2 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -30,6 +30,7 @@ import java.lang.reflect.Parameter; import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.stream.Collectors; class SWCommandUtils { @@ -37,10 +38,18 @@ class SWCommandUtils { throw new IllegalStateException("Utility Class"); } - static final Map, Function> MAPPER_FUNCTIONS = new HashMap<>(); + static final Map, TypeMapper> MAPPER_FUNCTIONS = new HashMap<>(); - static final Function ERROR_FUNCTION = s -> { - throw new SecurityException(s); + static final TypeMapper ERROR_FUNCTION = new TypeMapper<>() { + @Override + public Object map(String s) { + throw new SecurityException(); + } + + @Override + public List tabCompletes(String s) { + return Collections.emptyList(); + } }; static final BiFunction>, String, Enum> ENUM_MAPPER = (enumClass, s) -> { @@ -52,18 +61,157 @@ class SWCommandUtils { }; static { - MAPPER_FUNCTIONS.put(boolean.class, Boolean::parseBoolean); - MAPPER_FUNCTIONS.put(Boolean.class, Boolean::parseBoolean); - MAPPER_FUNCTIONS.put(float.class, Float::parseFloat); - MAPPER_FUNCTIONS.put(Float.class, Float::parseFloat); - MAPPER_FUNCTIONS.put(double.class, Double::parseDouble); - MAPPER_FUNCTIONS.put(Double.class, Double::parseDouble); - MAPPER_FUNCTIONS.put(int.class, Integer::parseInt); - MAPPER_FUNCTIONS.put(Integer.class, Integer::parseInt); - MAPPER_FUNCTIONS.put(String.class, s -> s); - MAPPER_FUNCTIONS.put(StringBuilder.class, StringBuilder::new); - MAPPER_FUNCTIONS.put(Player.class, Bukkit::getPlayer); - MAPPER_FUNCTIONS.put(UUID.class, UUID::fromString); + MAPPER_FUNCTIONS.put(boolean.class, new TypeMapper() { + @Override + public Boolean map(String s) { + return Boolean.parseBoolean(s); + } + + @Override + public List tabCompletes(String s) { + return Arrays.asList("true", "false"); + } + }); + MAPPER_FUNCTIONS.put(Boolean.class, new TypeMapper() { + @Override + public Boolean map(String s) { + return Boolean.parseBoolean(s); + } + + @Override + public List tabCompletes(String s) { + return Arrays.asList("true", "false"); + } + }); + MAPPER_FUNCTIONS.put(float.class, new TypeMapper() { + @Override + public Float map(String s) { + return Float.parseFloat(s); + } + + @Override + public List tabCompletes(String s) { + try { + Float.parseFloat(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + } + }); + MAPPER_FUNCTIONS.put(Float.class, new TypeMapper() { + @Override + public Float map(String s) { + return Float.parseFloat(s); + } + + @Override + public List tabCompletes(String s) { + try { + Float.parseFloat(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + } + }); + MAPPER_FUNCTIONS.put(double.class, new TypeMapper() { + @Override + public Double map(String s) { + return Double.parseDouble(s); + } + + @Override + public List tabCompletes(String s) { + try { + Double.parseDouble(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + } + }); + MAPPER_FUNCTIONS.put(Double.class, new TypeMapper() { + @Override + public Double map(String s) { + return Double.parseDouble(s); + } + + @Override + public List tabCompletes(String s) { + try { + Double.parseDouble(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + } + }); + MAPPER_FUNCTIONS.put(int.class, new TypeMapper() { + @Override + public Integer map(String s) { + return Integer.parseInt(s); + } + + @Override + public List tabCompletes(String s) { + try { + Integer.parseInt(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + } + }); + MAPPER_FUNCTIONS.put(Integer.class, new TypeMapper() { + @Override + public Integer map(String s) { + return Integer.parseInt(s); + } + + @Override + public List tabCompletes(String s) { + try { + Integer.parseInt(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + } + }); + MAPPER_FUNCTIONS.put(String.class, new TypeMapper() { + @Override + public String map(String s) { + return s; + } + + @Override + public List tabCompletes(String s) { + return Collections.singletonList(s); + } + }); + MAPPER_FUNCTIONS.put(StringBuilder.class, new TypeMapper() { + @Override + public StringBuilder map(String s) { + return new StringBuilder(s); + } + + @Override + public List tabCompletes(String s) { + return Collections.singletonList(s); + } + }); + MAPPER_FUNCTIONS.put(Player.class, new TypeMapper() { + @Override + public Player map(String s) { + return Bukkit.getPlayer(s); + } + + @Override + public List tabCompletes(String s) { + return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + } + }); } static final CommandMap commandMap; @@ -119,7 +267,7 @@ class SWCommandUtils { Class> enumClass = (Class>) clazz; return s -> ENUM_MAPPER.apply(enumClass, s); } else { - return s -> MAPPER_FUNCTIONS.getOrDefault(clazz, ERROR_FUNCTION).apply(s); + return s -> MAPPER_FUNCTIONS.getOrDefault(clazz, ERROR_FUNCTION).map(s); } } @@ -131,7 +279,7 @@ class SWCommandUtils { } } - public static void addMapper(Class clazz, Function mapper) { + public static void addMapper(Class clazz, TypeMapper mapper) { if (MAPPER_FUNCTIONS.containsKey(clazz)) return; MAPPER_FUNCTIONS.put(clazz, mapper); } diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java new file mode 100644 index 0000000..119c217 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java @@ -0,0 +1,29 @@ +/* + * 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 java.util.List; + +public interface TypeMapper { + + T map(String s); + List tabCompletes(String s); + +} From 03bbdcfe29b8a405f017ad495bfe829efbff81d3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 13 Mar 2021 16:02:44 +0100 Subject: [PATCH 12/71] Add SWCommandUtils.addMapper --- .../de/steamwar/command/SWCommandUtils.java | 72 +++---------------- 1 file changed, 9 insertions(+), 63 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index de7c1d2..2ee5b0b 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -61,7 +61,7 @@ class SWCommandUtils { }; static { - MAPPER_FUNCTIONS.put(boolean.class, new TypeMapper() { + addMapper(boolean.class, Boolean.class, new TypeMapper() { @Override public Boolean map(String s) { return Boolean.parseBoolean(s); @@ -72,18 +72,7 @@ class SWCommandUtils { return Arrays.asList("true", "false"); } }); - MAPPER_FUNCTIONS.put(Boolean.class, new TypeMapper() { - @Override - public Boolean map(String s) { - return Boolean.parseBoolean(s); - } - - @Override - public List tabCompletes(String s) { - return Arrays.asList("true", "false"); - } - }); - MAPPER_FUNCTIONS.put(float.class, new TypeMapper() { + addMapper(float.class, Float.class, new TypeMapper() { @Override public Float map(String s) { return Float.parseFloat(s); @@ -99,23 +88,7 @@ class SWCommandUtils { } } }); - MAPPER_FUNCTIONS.put(Float.class, new TypeMapper() { - @Override - public Float map(String s) { - return Float.parseFloat(s); - } - - @Override - public List tabCompletes(String s) { - try { - Float.parseFloat(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - } - }); - MAPPER_FUNCTIONS.put(double.class, new TypeMapper() { + addMapper(double.class, Double.class, new TypeMapper() { @Override public Double map(String s) { return Double.parseDouble(s); @@ -131,39 +104,7 @@ class SWCommandUtils { } } }); - MAPPER_FUNCTIONS.put(Double.class, new TypeMapper() { - @Override - public Double map(String s) { - return Double.parseDouble(s); - } - - @Override - public List tabCompletes(String s) { - try { - Double.parseDouble(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - } - }); - MAPPER_FUNCTIONS.put(int.class, new TypeMapper() { - @Override - public Integer map(String s) { - return Integer.parseInt(s); - } - - @Override - public List tabCompletes(String s) { - try { - Integer.parseInt(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - } - }); - MAPPER_FUNCTIONS.put(Integer.class, new TypeMapper() { + addMapper(int.class, Integer.class, new TypeMapper() { @Override public Integer map(String s) { return Integer.parseInt(s); @@ -214,6 +155,11 @@ class SWCommandUtils { }); } + private static void addMapper(Class clazz, Class alternativeClazz, TypeMapper mapper) { + MAPPER_FUNCTIONS.put(clazz, mapper); + MAPPER_FUNCTIONS.put(alternativeClazz, mapper); + } + static final CommandMap commandMap; static { From add406a8aaa79040e863a0c6ea1123b83bc23779 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 13 Mar 2021 16:17:31 +0100 Subject: [PATCH 13/71] Add better TabComplete for only Command implementations --- .../de/steamwar/command/InternalCommand.java | 25 +++++++++++++++++++ .../src/de/steamwar/command/SWCommand.java | 7 +++++- .../de/steamwar/command/SWCommandUtils.java | 3 ++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java index 5595992..945c78a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java @@ -24,17 +24,22 @@ 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) { @@ -51,4 +56,24 @@ class InternalCommand { return true; } + List tabComplete(String[] args) { + if (args.length > parameters.length - increment) { + if (parameters[parameters.length - 1].isVarArgs()) { + Class clazz = parameters[parameters.length - 1].getType().getComponentType(); + try { + return SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(clazz, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); + } catch (Exception e) { + // Ignored + } + } + return Collections.emptyList(); + } + Class clazz = parameters[args.length - increment + 1].getType(); + try { + return SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(clazz, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); + } catch (Exception e) { + return Collections.emptyList(); + } + } + } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 350d574..7f83dc4 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -57,7 +57,6 @@ public abstract class SWCommand { @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { - // TODO: add better tab complete, command based List strings = new ArrayList<>(subCommandTabCompletes.getOrDefault(args.length, new HashSet<>())); for (InternalTabComplete internalTabComplete : tabCompleteSet) { SWCommandUtils.TabComplete tabComplete = internalTabComplete.invoke(sender, args); @@ -65,6 +64,12 @@ public abstract class SWCommand { strings.addAll(tabComplete.tabCompletes); } } + for (InternalCommand internalCommand : commandSet) { + List stringList = internalCommand.tabComplete(args); + if (stringList != null) { + strings.addAll(stringList); + } + } strings = new ArrayList<>(strings); for (int i = strings.size() - 1; i >= 0; i--) { if (!strings.get(i).startsWith(args[args.length - 1])) { diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 2ee5b0b..636f08b 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -225,7 +225,8 @@ class SWCommandUtils { } } - public static void addMapper(Class clazz, TypeMapper mapper) { + public static void addMapper(Class clazz, TypeMapper mapper) { + if (clazz.isEnum()) return; if (MAPPER_FUNCTIONS.containsKey(clazz)) return; MAPPER_FUNCTIONS.put(clazz, mapper); } From f0bf20e96022625fff4619d6e5354ce45e879aab Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 13 Mar 2021 19:42:28 +0100 Subject: [PATCH 14/71] Add SWCommand.Mapper Add mapper support to internal reflections Add better tab complete support for to InternalCommand --- .../de/steamwar/command/InternalCommand.java | 20 ++++++--- .../steamwar/command/InternalTabComplete.java | 4 +- .../src/de/steamwar/command/SWCommand.java | 36 ++++++++++++---- .../de/steamwar/command/SWCommandUtils.java | 42 ++++++++++++------- .../src/de/steamwar/command/TypeMapper.java | 3 +- 5 files changed, 74 insertions(+), 31 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java index 945c78a..6481fa3 100644 --- a/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/InternalCommand.java @@ -43,7 +43,9 @@ class InternalCommand { } boolean invoke(CommandSender commandSender, String[] args) { - if (args.length < parameters.length - 1) return false; + if (args.length < parameters.length - 1) { + return false; + } try { Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, method, parameters, args); method.setAccessible(true); @@ -59,18 +61,26 @@ class InternalCommand { List tabComplete(String[] args) { if (args.length > parameters.length - increment) { if (parameters[parameters.length - 1].isVarArgs()) { - Class clazz = parameters[parameters.length - 1].getType().getComponentType(); + 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(clazz, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); + return SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); } catch (Exception e) { // Ignored } } return Collections.emptyList(); } - Class clazz = parameters[args.length - increment + 1].getType(); + 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(clazz, SWCommandUtils.ERROR_FUNCTION).tabCompletes(args[args.length - 1]); + 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 index 44effb6..cb7c655 100644 --- a/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java +++ b/SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java @@ -38,7 +38,9 @@ class InternalTabComplete { } SWCommandUtils.TabComplete invoke(CommandSender commandSender, String[] args) { - if (args.length < parameters.length - 1) return null; + if (args.length < parameters.length - 1) { + return null; + } try { Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, method, parameters, args); method.setAccessible(true); diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 7f83dc4..81e7fed 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -36,7 +36,8 @@ public abstract class SWCommand { private final Set commandSet = new HashSet<>(); private final Set tabCompleteSet = new HashSet<>(); private final Map> subCommandTabCompletes = new HashMap<>(); - private Consumer helpMessage = sender -> {}; + private Consumer helpMessage = sender -> { + }; protected SWCommand(String command) { this(command, new String[0]); @@ -82,12 +83,16 @@ public abstract class SWCommand { for (Method method : getClass().getDeclaredMethods()) { Register register = method.getDeclaredAnnotation(Register.class); - if (register == null) continue; + 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 (!validMethod(method)) { + continue; + } if (method.getReturnType() == Void.TYPE) { commandSet.add(new InternalCommand(this, method)); } @@ -99,16 +104,27 @@ public abstract class SWCommand { private boolean validMethod(Method method) { Parameter[] parameters = method.getParameters(); - if (parameters.length == 0) return false; - if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) return false; + if (parameters.length == 0) { + return false; + } + if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) { + return false; + } 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(); } - if (clazz.isEnum()) continue; - if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz)) return false; + if (clazz.isEnum()) { + continue; + } + String name = clazz.getTypeName(); + Mapper mapper = parameter.getAnnotation(Mapper.class); + if (mapper != null) { + name = mapper.mapper(); + } + if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return false; } return true; } @@ -128,4 +144,10 @@ public abstract class SWCommand { String[] subCommand() default {}; } + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.PARAMETER}) + protected @interface Mapper { + String mapper(); + } + } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 636f08b..4df770d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -38,7 +38,7 @@ class SWCommandUtils { throw new IllegalStateException("Utility Class"); } - static final Map, TypeMapper> MAPPER_FUNCTIONS = new HashMap<>(); + static final Map> MAPPER_FUNCTIONS = new HashMap<>(); static final TypeMapper ERROR_FUNCTION = new TypeMapper<>() { @Override @@ -120,7 +120,7 @@ class SWCommandUtils { } } }); - MAPPER_FUNCTIONS.put(String.class, new TypeMapper() { + MAPPER_FUNCTIONS.put(String.class.getTypeName(), new TypeMapper() { @Override public String map(String s) { return s; @@ -131,7 +131,7 @@ class SWCommandUtils { return Collections.singletonList(s); } }); - MAPPER_FUNCTIONS.put(StringBuilder.class, new TypeMapper() { + MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), new TypeMapper() { @Override public StringBuilder map(String s) { return new StringBuilder(s); @@ -142,7 +142,7 @@ class SWCommandUtils { return Collections.singletonList(s); } }); - MAPPER_FUNCTIONS.put(Player.class, new TypeMapper() { + MAPPER_FUNCTIONS.put(Player.class.getTypeName(), new TypeMapper() { @Override public Player map(String s) { return Bukkit.getPlayer(s); @@ -156,8 +156,8 @@ class SWCommandUtils { } private static void addMapper(Class clazz, Class alternativeClazz, TypeMapper mapper) { - MAPPER_FUNCTIONS.put(clazz, mapper); - MAPPER_FUNCTIONS.put(alternativeClazz, mapper); + MAPPER_FUNCTIONS.put(clazz.getTypeName(), mapper); + MAPPER_FUNCTIONS.put(alternativeClazz.getTypeName(), mapper); } static final CommandMap commandMap; @@ -189,14 +189,13 @@ class SWCommandUtils { } for (int i = subCommandIndex; i < parameters.length - (varArgs ? 1 : 0); i++) { - Class clazz = parameters[i].getType(); - arguments[i] = mapper(clazz).apply(args[i - 1]); + arguments[i] = mapper(parameters[i]).apply(args[i - 1]); } if (varArgs) { Object[] varArgument = new Object[args.length - parameters.length + 2]; arguments[arguments.length - 1] = varArgument; - Function mapper = mapper(parameters[parameters.length - 1].getType().getComponentType()); + Function mapper = mapper(parameters[parameters.length - 1]); int index = 0; for (int i = parameters.length - 2; i < args.length; i++) { @@ -208,13 +207,25 @@ class SWCommandUtils { } @SuppressWarnings("unchecked") - private static Function mapper(Class clazz) { + private static Function mapper(Parameter parameter) { + Class clazz = parameter.getType(); + if (parameter.isVarArgs()) { + clazz = clazz.getComponentType(); + } + if (clazz.isEnum()) { Class> enumClass = (Class>) clazz; return s -> ENUM_MAPPER.apply(enumClass, s); - } else { - return s -> MAPPER_FUNCTIONS.getOrDefault(clazz, ERROR_FUNCTION).map(s); } + + String name = clazz.getTypeName(); + SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); + if (mapper != null) { + name = mapper.mapper(); + } + + TypeMapper typeMapper = MAPPER_FUNCTIONS.getOrDefault(name, ERROR_FUNCTION); + return typeMapper::map; } public static class TabComplete { @@ -225,10 +236,9 @@ class SWCommandUtils { } } - public static void addMapper(Class clazz, TypeMapper mapper) { - if (clazz.isEnum()) return; - if (MAPPER_FUNCTIONS.containsKey(clazz)) return; - MAPPER_FUNCTIONS.put(clazz, mapper); + public static void addMapper(String name, TypeMapper mapper) { + if (MAPPER_FUNCTIONS.containsKey(name)) return; + MAPPER_FUNCTIONS.put(name, mapper); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java index 119c217..c9f34e4 100644 --- a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java +++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java @@ -22,8 +22,7 @@ package de.steamwar.command; import java.util.List; public interface TypeMapper { - T map(String s); - List tabCompletes(String s); + List tabCompletes(String s); } From ea4d6f2a0a88be0f56d52d4f577fb7fa17254a2c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:23:18 +0100 Subject: [PATCH 15/71] Simplify CommandFramework Remove InternalCommand.java Remove InternalTabComplete.java Add SubCommand --- .../de/steamwar/command/InternalCommand.java | 89 ------------------ .../steamwar/command/InternalTabComplete.java | 55 ----------- .../src/de/steamwar/command/SWCommand.java | 35 ++----- .../de/steamwar/command/SWCommandUtils.java | 37 ++++---- .../src/de/steamwar/command/SubCommand.java | 92 +++++++++++++++++++ 5 files changed, 117 insertions(+), 191 deletions(-) delete mode 100644 SpigotCore_Main/src/de/steamwar/command/InternalCommand.java delete mode 100644 SpigotCore_Main/src/de/steamwar/command/InternalTabComplete.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/SubCommand.java 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; + } + +} From 23ec2f62f7587113d386c2be30762cf78b0f57c3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:25:48 +0100 Subject: [PATCH 16/71] Fix SubCommand.invoke --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 96a21ec..7c6dbb8 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -78,7 +78,7 @@ class SubCommand { method.invoke(swCommand, objects); } catch (IllegalArgumentException | IllegalAccessException e) { throw new SecurityException(e.getMessage(), e); - } catch (InvocationTargetException e) { + } catch (InvocationTargetException | SecurityException e) { return false; } return true; From 7ab2d5e55d9f2640a1e3656b6ad68a380d8a5801 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:27:02 +0100 Subject: [PATCH 17/71] Remove SWCommandUtils.TabComplete --- .../src/de/steamwar/command/SWCommandUtils.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index f3ddf9c..ce04274 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -223,14 +223,6 @@ class SWCommandUtils { return typeMapper::map; } - public static class TabComplete { - final List tabCompletes; - - public TabComplete(List tabCompletes) { - this.tabCompletes = tabCompletes; - } - } - public static void addMapper(String name, TypeMapper mapper) { if (MAPPER_FUNCTIONS.containsKey(name)) return; MAPPER_FUNCTIONS.put(name, mapper); From 377befea4705f5918ebcff97c0073adc7b7c0e71 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:29:13 +0100 Subject: [PATCH 18/71] Optimize Imports --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 2 -- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 1 - 2 files changed, 3 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index ce04274..c15ee14 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -21,11 +21,9 @@ package de.steamwar.command; import org.bukkit.Bukkit; import org.bukkit.command.CommandMap; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; import java.util.function.BiFunction; diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 7c6dbb8..0623f67 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -6,7 +6,6 @@ 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; From 10cb766be9cc366de0ed4cf36396bab1fb352b09 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:30:28 +0100 Subject: [PATCH 19/71] Fix catch of SubCommand --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 0623f67..3a62277 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -77,7 +77,7 @@ class SubCommand { method.invoke(swCommand, objects); } catch (IllegalArgumentException | IllegalAccessException e) { throw new SecurityException(e.getMessage(), e); - } catch (InvocationTargetException | SecurityException e) { + } catch (InvocationTargetException | RuntimeException e) { return false; } return true; From e9fbfcac708898bf94bbe9c558a56319d2a90b6b Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:38:42 +0100 Subject: [PATCH 20/71] Remove SWCommandUtils.mapper --- .../de/steamwar/command/SWCommandUtils.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index c15ee14..5322a14 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -199,28 +199,6 @@ class SWCommandUtils { return arguments; } - @SuppressWarnings("unchecked") - private static Function mapper(Parameter parameter) { - Class clazz = parameter.getType(); - if (parameter.isVarArgs()) { - clazz = clazz.getComponentType(); - } - - if (clazz.isEnum()) { - Class> enumClass = (Class>) clazz; - return s -> ENUM_MAPPER.apply(enumClass, s); - } - - String name = clazz.getTypeName(); - SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); - if (mapper != null) { - name = mapper.mapper(); - } - - TypeMapper typeMapper = MAPPER_FUNCTIONS.getOrDefault(name, ERROR_FUNCTION); - return typeMapper::map; - } - public static void addMapper(String name, TypeMapper mapper) { if (MAPPER_FUNCTIONS.containsKey(name)) return; MAPPER_FUNCTIONS.put(name, mapper); From 9adf9f139b12c80d32ca4a5ec3631fa5c8aaaf43 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 12:39:01 +0100 Subject: [PATCH 21/71] Optimize Imports --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 5322a14..9ff0169 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -24,10 +24,8 @@ import org.bukkit.command.CommandMap; import org.bukkit.entity.Player; import java.lang.reflect.Field; -import java.lang.reflect.Parameter; import java.util.*; import java.util.function.BiFunction; -import java.util.function.Function; import java.util.stream.Collectors; class SWCommandUtils { From 09e6f0baa8050fc9df0327ea1f84a551a7f0a6bc Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 13:35:51 +0100 Subject: [PATCH 22/71] Fix SWCommand.Register Fix SWCommand.Mapper --- .../src/de/steamwar/acommand/TestCommand.java | 23 +++++++++++++++++++ .../src/de/steamwar/command/SWCommand.java | 6 ++--- .../src/de/steamwar/command/SubCommand.java | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java new file mode 100644 index 0000000..c0c8d9a --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -0,0 +1,23 @@ +package de.steamwar.acommand; + +import de.steamwar.command.SWCommand; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +public class TestCommand extends SWCommand { + + public TestCommand() { + super("test"); + } + + @Register + public void test(Player player) { + + } + + @Register({"two"}) + public void testTwo(Player player, int i, @Mapper("Hello World") Material material) { + + } + +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index e5923e0..4919a41 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -105,7 +105,7 @@ public abstract class SWCommand { String name = clazz.getTypeName(); Mapper mapper = parameter.getAnnotation(Mapper.class); if (mapper != null) { - name = mapper.mapper(); + name = mapper.value(); } if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return false; } @@ -124,13 +124,13 @@ public abstract class SWCommand { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) protected @interface Register { - String[] subCommand() default {}; + String[] value() default {}; } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) protected @interface Mapper { - String mapper(); + String value(); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 3a62277..ab0c8ca 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -25,7 +25,7 @@ class SubCommand { Parameter[] parameters = method.getParameters(); commandSenderFunction = sender -> parameters[0].getType().cast(sender); SWCommand.Register register = method.getAnnotation(SWCommand.Register.class); - subCommand = register.subCommand(); + subCommand = register.value(); arguments = new TypeMapper[parameters.length - 1]; for (int i = 1; i < parameters.length; i++) { @@ -59,7 +59,7 @@ class SubCommand { String name = clazz.getTypeName(); SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); if (mapper != null) { - name = mapper.mapper(); + name = mapper.value(); } arguments[i] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); From 9773b9d7ea19483c1c4284445623fe672fbfde4d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 13:38:14 +0100 Subject: [PATCH 23/71] Fix TestCommand --- SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index c0c8d9a..a09a896 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -7,14 +7,18 @@ import org.bukkit.entity.Player; public class TestCommand extends SWCommand { public TestCommand() { + // Register this command as 'test' super("test"); } + // One Command, the first Parameter should be some kind of CommandSender @Register public void test(Player player) { } + // Another Command, subCommands can be implemented with the Register Annotation, + // you can Implement custom Mappers Annotation by @Mapper on a Parameter @Register({"two"}) public void testTwo(Player player, int i, @Mapper("Hello World") Material material) { From 97a8862b6281d4204e84f7456f73042dbde56734 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 14:13:35 +0100 Subject: [PATCH 24/71] Fix SWCommand Mapper stuff Add copyright to SubCommand --- .../src/de/steamwar/acommand/TestCommand.java | 49 ++++++++++++++++- .../src/de/steamwar/command/SWCommand.java | 53 ++++++++++++++----- .../src/de/steamwar/command/SubCommand.java | 19 +++++++ 3 files changed, 106 insertions(+), 15 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index a09a896..aa8ca89 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -1,9 +1,33 @@ +/* + * 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.acommand; import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeMapper; import org.bukkit.Material; import org.bukkit.entity.Player; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + public class TestCommand extends SWCommand { public TestCommand() { @@ -18,10 +42,33 @@ public class TestCommand extends SWCommand { } // Another Command, subCommands can be implemented with the Register Annotation, - // you can Implement custom Mappers Annotation by @Mapper on a Parameter + // you can use custom Mappers by putting a Mapper Annotation on a Parameter @Register({"two"}) public void testTwo(Player player, int i, @Mapper("Hello World") Material material) { } + // Add Custom Mapper when this command is registered, all Mapper of you class will be + // created first and than the Commands. Do not use this mapper outside your class, as + // it can only create failures. Use on your own risk. Definition order should be considered. + @Mapper("Hello World") + public TypeMapper materialTypeMapper() { + List tabCompletes = Arrays.stream(Material.values()) + .filter(Material::isSolid) + .map(Material::name) + .map(String::toLowerCase) + .collect(Collectors.toList()); + return new TypeMapper<>() { + @Override + public Material map(String s) { + return Material.valueOf(s.toUpperCase()); + } + + @Override + public List tabCompletes(String s) { + return tabCompletes; + } + }; + } + } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 4919a41..de49a86 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -74,24 +74,26 @@ public abstract class SWCommand { }); for (Method method : getClass().getDeclaredMethods()) { - Register register = method.getDeclaredAnnotation(Register.class); - if (register == null) { - continue; - } - if (!validMethod(method)) { - continue; - } - commandSet.add(new SubCommand(this, method)); + addMapper(method); + } + for (Method method : getClass().getDeclaredMethods()) { + addCommand(method); } } - private boolean validMethod(Method method) { + private void addCommand(Method method) { + Register register = method.getDeclaredAnnotation(Register.class); + Mapper methodMapper = method.getDeclaredAnnotation(Mapper.class); + if (register == null || methodMapper != null) { + return; + } + Parameter[] parameters = method.getParameters(); if (parameters.length == 0) { - return false; + return; } if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) { - return false; + return; } for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; @@ -107,9 +109,32 @@ public abstract class SWCommand { if (mapper != null) { name = mapper.value(); } - if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return false; + if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return; + } + commandSet.add(new SubCommand(this, method)); + } + + private void addMapper(Method method) { + Register register = method.getDeclaredAnnotation(Register.class); + Mapper methodMapper = method.getDeclaredAnnotation(Mapper.class); + if (register != null || methodMapper == null) { + return; + } + + Parameter[] parameters = method.getParameters(); + if (parameters.length != 0) { + return; + } + if (method.getReturnType() != TypeMapper.class) { + return; + } + try { + method.setAccessible(true); + Object object = method.invoke(this); + SWCommandUtils.addMapper(methodMapper.value(), (TypeMapper) object); + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); } - return true; } protected final void setHelpMessage(Consumer helpMessage) { @@ -128,7 +153,7 @@ public abstract class SWCommand { } @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.PARAMETER}) + @Target({ElementType.PARAMETER, ElementType.METHOD}) protected @interface Mapper { String value(); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index ab0c8ca..b04abf5 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -1,3 +1,22 @@ +/* + * 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; From 451d30a4967002c8e03fae0c87988c3660a70b39 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 14:16:03 +0100 Subject: [PATCH 25/71] Add Mapper support for Enum Parameters --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index b04abf5..7af8a46 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -55,7 +55,8 @@ class SubCommand { clazz = clazz.getComponentType(); } - if (clazz.isEnum()) { + SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); + if (clazz.isEnum() && mapper == null) { Class> enumClass = (Class>) clazz; List tabCompletes = new ArrayList<>(); for (Enum enumConstant : enumClass.getEnumConstants()) { @@ -76,7 +77,6 @@ class SubCommand { } String name = clazz.getTypeName(); - SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); if (mapper != null) { name = mapper.value(); } From 57b5c2b81ba3db87b8adc928de2d89f9a18f0214 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 14:17:34 +0100 Subject: [PATCH 26/71] Fix TestCommand --- SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index aa8ca89..9e6a68e 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -44,21 +44,21 @@ public class TestCommand extends SWCommand { // Another Command, subCommands can be implemented with the Register Annotation, // you can use custom Mappers by putting a Mapper Annotation on a Parameter @Register({"two"}) - public void testTwo(Player player, int i, @Mapper("Hello World") Material material) { + public void testTwo(Player player, int i, @Mapper("solidMaterial") Material material) { } // Add Custom Mapper when this command is registered, all Mapper of you class will be // created first and than the Commands. Do not use this mapper outside your class, as // it can only create failures. Use on your own risk. Definition order should be considered. - @Mapper("Hello World") + @Mapper("solidMaterial") public TypeMapper materialTypeMapper() { List tabCompletes = Arrays.stream(Material.values()) .filter(Material::isSolid) .map(Material::name) .map(String::toLowerCase) .collect(Collectors.toList()); - return new TypeMapper<>() { + return new TypeMapper() { @Override public Material map(String s) { return Material.valueOf(s.toUpperCase()); From ae26f2837d5dcb043c48627ce92ea160b5f1f2bd Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 14:21:36 +0100 Subject: [PATCH 27/71] Fix SWCommand with Mapper Simplify SWCommand registering mapper and commands --- .../src/de/steamwar/command/SWCommand.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index de49a86..c765932 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -73,15 +73,15 @@ public abstract class SWCommand { } }); + Set commandMethods = new HashSet<>(); for (Method method : getClass().getDeclaredMethods()) { addMapper(method); + addCommand(method, commandMethods); } - for (Method method : getClass().getDeclaredMethods()) { - addCommand(method); - } + commandMethods.forEach(method -> commandSet.add(new SubCommand(this, method))); } - private void addCommand(Method method) { + private void addCommand(Method method, Set commandMethods) { Register register = method.getDeclaredAnnotation(Register.class); Mapper methodMapper = method.getDeclaredAnnotation(Mapper.class); if (register == null || methodMapper != null) { @@ -101,17 +101,17 @@ public abstract class SWCommand { if (parameter.isVarArgs() && i == parameters.length - 1) { clazz = parameter.getType().getComponentType(); } - if (clazz.isEnum()) { + Mapper mapper = parameter.getAnnotation(Mapper.class); + if (clazz.isEnum() && mapper == null) { continue; } String name = clazz.getTypeName(); - Mapper mapper = parameter.getAnnotation(Mapper.class); if (mapper != null) { name = mapper.value(); } if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return; } - commandSet.add(new SubCommand(this, method)); + commandMethods.add(method); } private void addMapper(Method method) { From ed0ee1b0a7c558abf8be3dea5576934e69da45d3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 19:52:27 +0100 Subject: [PATCH 28/71] Add SubCommand.tabComplete --- .../src/de/steamwar/command/SubCommand.java | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 7af8a46..8dd4aec 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -21,10 +21,13 @@ package de.steamwar.command; import org.bukkit.command.CommandSender; +import java.io.IOException; 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.Collections; import java.util.List; import java.util.function.Function; @@ -103,8 +106,33 @@ class SubCommand { } List tabComplete(CommandSender commandSender, String[] args) { - // TODO: implement tabCompleting for SubCommand - return null; + List argsList = Arrays.asList(args); + for (int i = 0; i < subCommand.length; i++) { + String s = argsList.remove(0); + if (argsList.isEmpty()) return Collections.singletonList(subCommand[i]); + if (!subCommand[i].equals(s)) return Collections.emptyList(); + } + for (int i = 0; i < arguments.length; i++) { + String s = argsList.remove(0); + if (argsList.isEmpty()) return arguments[i].tabCompletes(s); + try { + arguments[i].map(s); + } catch (Exception e) { + return Collections.emptyList(); + } + } + if (varArgs && !argsList.isEmpty()) { + while (!argsList.isEmpty()) { + String s = argsList.remove(0); + if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(s); + try { + arguments[arguments.length - 1].map(s); + } catch (Exception e) { + return Collections.emptyList(); + } + } + } + return Collections.emptyList(); } } From 1b10c96dc6768f4803d05783bbe2297a161fa187 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 20:10:50 +0100 Subject: [PATCH 29/71] Optimize imports SubCommand --- .../src/de/steamwar/command/SubCommand.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 8dd4aec..8d50f73 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -21,7 +21,6 @@ package de.steamwar.command; import org.bukkit.command.CommandSender; -import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Parameter; @@ -107,16 +106,16 @@ class SubCommand { List tabComplete(CommandSender commandSender, String[] args) { List argsList = Arrays.asList(args); - for (int i = 0; i < subCommand.length; i++) { + for (String value : subCommand) { String s = argsList.remove(0); - if (argsList.isEmpty()) return Collections.singletonList(subCommand[i]); - if (!subCommand[i].equals(s)) return Collections.emptyList(); + if (argsList.isEmpty()) return Collections.singletonList(value); + if (!value.equals(s)) return Collections.emptyList(); } - for (int i = 0; i < arguments.length; i++) { + for (TypeMapper argument : arguments) { String s = argsList.remove(0); - if (argsList.isEmpty()) return arguments[i].tabCompletes(s); + if (argsList.isEmpty()) return argument.tabCompletes(s); try { - arguments[i].map(s); + argument.map(s); } catch (Exception e) { return Collections.emptyList(); } From 472b6f46d5e21290148c598095cbc55145e9030d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 20:26:44 +0100 Subject: [PATCH 30/71] Add help command System to SWCommand --- .../src/de/steamwar/command/SWCommand.java | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index c765932..432dd78 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -22,20 +22,15 @@ package de.steamwar.command; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.*; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; -import java.util.function.Consumer; public abstract class SWCommand { private final Set commandSet = new HashSet<>(); - private Consumer helpMessage = sender -> { - }; + private final Set commandHelpSet = new HashSet<>(); protected SWCommand(String command) { this(command, new String[0]); @@ -50,7 +45,11 @@ public abstract class SWCommand { return false; } } - helpMessage.accept(sender); + for (SubCommand subCommand : commandHelpSet) { + if (subCommand.invoke(sender, args)) { + return false; + } + } return false; } @@ -77,14 +76,14 @@ public abstract class SWCommand { for (Method method : getClass().getDeclaredMethods()) { addMapper(method); addCommand(method, commandMethods); + addHelp(method); } commandMethods.forEach(method -> commandSet.add(new SubCommand(this, method))); } private void addCommand(Method method, Set commandMethods) { - Register register = method.getDeclaredAnnotation(Register.class); - Mapper methodMapper = method.getDeclaredAnnotation(Mapper.class); - if (register == null || methodMapper != null) { + Register register = getAnnotation(method, Register.class); + if (register == null) { return; } @@ -114,10 +113,25 @@ public abstract class SWCommand { commandMethods.add(method); } + private void addHelp(Method method) { + RegisterHelp registerHelp = getAnnotation(method, RegisterHelp.class); + if (registerHelp == null) { + return; + } + + Parameter[] parameters = method.getParameters(); + if (parameters.length != 1) { + return; + } + if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) { + return; + } + commandHelpSet.add(new SubCommand(this, method)); + } + private void addMapper(Method method) { - Register register = method.getDeclaredAnnotation(Register.class); - Mapper methodMapper = method.getDeclaredAnnotation(Mapper.class); - if (register != null || methodMapper == null) { + Mapper mapper = getAnnotation(method, Mapper.class); + if (mapper == null) { return; } @@ -131,19 +145,15 @@ public abstract class SWCommand { try { method.setAccessible(true); Object object = method.invoke(this); - SWCommandUtils.addMapper(methodMapper.value(), (TypeMapper) object); + SWCommandUtils.addMapper(mapper.value(), (TypeMapper) object); } catch (Exception e) { throw new SecurityException(e.getMessage(), e); } } - protected final void setHelpMessage(Consumer helpMessage) { - assert helpMessage != null; - this.helpMessage = helpMessage; - } - - protected final void sendHelpMessage(T sender) { - helpMessage.accept(sender); + private T getAnnotation(Method method, Class annotation) { + if (method.getAnnotations().length != 1) return null; + return method.getAnnotation(annotation); } @Retention(RetentionPolicy.RUNTIME) @@ -152,6 +162,12 @@ public abstract class SWCommand { String[] value() default {}; } + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + protected @interface RegisterHelp { + String[] value() default {}; + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.METHOD}) protected @interface Mapper { From 05f8129705dc5f1e0bbd640715e1ca90fd89004c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 20:27:48 +0100 Subject: [PATCH 31/71] Add help command System to SWCommand --- SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index 9e6a68e..90800e1 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -35,6 +35,12 @@ public class TestCommand extends SWCommand { super("test"); } + // One Help Command, the first Parameter should be some kind of CommandSender + @RegisterHelp + public void testHelp(Player player) { + player.sendMessage("This is your help message"); + } + // One Command, the first Parameter should be some kind of CommandSender @Register public void test(Player player) { From 4bedbe227540b7be6099bb0f20c820ecc2c25b85 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 20:46:02 +0100 Subject: [PATCH 32/71] Add better Enum handling for Custom TypeMapper Add SWCommandUtils.getAnnotation Add GameMode mapper for better gamemode handling --- .../src/de/steamwar/command/SWCommand.java | 14 +++---- .../de/steamwar/command/SWCommandUtils.java | 37 +++++++++++++++++++ .../src/de/steamwar/command/SubCommand.java | 13 +++++-- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 432dd78..725f451 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -22,11 +22,16 @@ package de.steamwar.command; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import java.lang.annotation.*; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; +import static de.steamwar.command.SWCommandUtils.getAnnotation; + public abstract class SWCommand { private final Set commandSet = new HashSet<>(); @@ -101,7 +106,7 @@ public abstract class SWCommand { clazz = parameter.getType().getComponentType(); } Mapper mapper = parameter.getAnnotation(Mapper.class); - if (clazz.isEnum() && mapper == null) { + if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) { continue; } String name = clazz.getTypeName(); @@ -151,11 +156,6 @@ public abstract class SWCommand { } } - private T getAnnotation(Method method, Class annotation) { - if (method.getAnnotations().length != 1) return null; - return method.getAnnotation(annotation); - } - @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) protected @interface Register { diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 9ff0169..f48bf08 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -20,10 +20,13 @@ package de.steamwar.command; import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.command.CommandMap; import org.bukkit.entity.Player; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.*; import java.util.function.BiFunction; import java.util.stream.Collectors; @@ -149,6 +152,35 @@ class SWCommandUtils { return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); } }); + MAPPER_FUNCTIONS.put(GameMode.class.getTypeName(), new TypeMapper() { + @Override + public GameMode map(String s) { + switch (s.toLowerCase()) { + case "s": + case "survival": + case "0": + return GameMode.SURVIVAL; + case "c": + case "creative": + case "1": + return GameMode.CREATIVE; + case "sp": + case "spectator": + case "3": + return GameMode.SPECTATOR; + case "a": + case "adventure": + case "2": + return GameMode.ADVENTURE; + } + throw new SecurityException(); + } + + @Override + public List tabCompletes(String s) { + return Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "specator", "3", "a", "adventure", "2"); + } + }); } private static void addMapper(Class clazz, Class alternativeClazz, TypeMapper mapper) { @@ -202,4 +234,9 @@ class SWCommandUtils { MAPPER_FUNCTIONS.put(name, mapper); } + static T getAnnotation(Method method, Class annotation) { + if (method.getAnnotations().length != 1) return null; + return method.getAnnotation(annotation); + } + } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 8d50f73..053aae3 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -45,8 +45,15 @@ class SubCommand { Parameter[] parameters = method.getParameters(); commandSenderFunction = sender -> parameters[0].getType().cast(sender); - SWCommand.Register register = method.getAnnotation(SWCommand.Register.class); - subCommand = register.value(); + SWCommand.Register register = SWCommandUtils.getAnnotation(method, SWCommand.Register.class); + SWCommand.RegisterHelp registerHelp = SWCommandUtils.getAnnotation(method, SWCommand.RegisterHelp.class); + if (register != null) { + subCommand = register.value(); + } else if (registerHelp != null) { + subCommand = registerHelp.value(); + } else { + throw new SecurityException(); + } arguments = new TypeMapper[parameters.length - 1]; for (int i = 1; i < parameters.length; i++) { @@ -58,7 +65,7 @@ class SubCommand { } SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); - if (clazz.isEnum() && mapper == null) { + if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) { Class> enumClass = (Class>) clazz; List tabCompletes = new ArrayList<>(); for (Enum enumConstant : enumClass.getEnumConstants()) { From a45a83e2d541ab7dc54310cf3ee0b155bbcb0629 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 25 Mar 2021 20:55:43 +0100 Subject: [PATCH 33/71] Add SWCommandUtils.createMapper --- .../de/steamwar/command/SWCommandUtils.java | 115 ++++++------------ 1 file changed, 38 insertions(+), 77 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index f48bf08..ebbcfaf 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -29,6 +29,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.function.BiFunction; +import java.util.function.Function; import java.util.stream.Collectors; class SWCommandUtils { @@ -60,87 +61,33 @@ class SWCommandUtils { }; static { - addMapper(boolean.class, Boolean.class, new TypeMapper() { - @Override - public Boolean map(String s) { - return Boolean.parseBoolean(s); - } - - @Override - public List tabCompletes(String s) { - return Arrays.asList("true", "false"); - } - }); - addMapper(float.class, Float.class, new TypeMapper() { - @Override - public Float map(String s) { - return Float.parseFloat(s); - } - - @Override - public List tabCompletes(String s) { - try { - Float.parseFloat(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - } - }); - addMapper(double.class, Double.class, new TypeMapper() { - @Override - public Double map(String s) { - return Double.parseDouble(s); - } - - @Override - public List tabCompletes(String s) { - try { - Double.parseDouble(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - } - }); - addMapper(int.class, Integer.class, new TypeMapper() { - @Override - public Integer map(String s) { - return Integer.parseInt(s); - } - - @Override - public List tabCompletes(String s) { - try { - Integer.parseInt(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - } - }); - MAPPER_FUNCTIONS.put(String.class.getTypeName(), new TypeMapper() { - @Override - public String map(String s) { - return s; - } - - @Override - public List tabCompletes(String s) { + addMapper(boolean.class, Boolean.class, createMapper(Boolean::parseBoolean, s -> Arrays.asList("true", "false"))); + addMapper(float.class, Float.class, createMapper(Float::parseFloat, s -> { + try { + Float.parseFloat(s); return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); } - }); - MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), new TypeMapper() { - @Override - public StringBuilder map(String s) { - return new StringBuilder(s); - } - - @Override - public List tabCompletes(String s) { + })); + addMapper(double.class, Double.class, createMapper(Double::parseDouble, s -> { + try { + Double.parseDouble(s); return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); } - }); + })); + addMapper(int.class, Integer.class, createMapper(Integer::parseInt, s -> { + try { + Integer.parseInt(s); + return Collections.singletonList(s); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + })); + MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList)); + MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), createMapper(StringBuilder::new, Collections::singletonList)); MAPPER_FUNCTIONS.put(Player.class.getTypeName(), new TypeMapper() { @Override public Player map(String s) { @@ -234,6 +181,20 @@ class SWCommandUtils { MAPPER_FUNCTIONS.put(name, mapper); } + public static TypeMapper createMapper(Function mapper, Function> tabCompleter) { + return new TypeMapper() { + @Override + public T map(String s) { + return mapper.apply(s); + } + + @Override + public List tabCompletes(String s) { + return tabCompleter.apply(s); + } + }; + } + static T getAnnotation(Method method, Class annotation) { if (method.getAnnotations().length != 1) return null; return method.getAnnotation(annotation); From 9b01cbf7bf09986a739ae8af59e39ca5d68554cd Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 08:40:05 +0100 Subject: [PATCH 34/71] Optimize SWCommandUtils --- .../de/steamwar/command/SWCommandUtils.java | 51 ++++++------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index ebbcfaf..3c3f9b1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -88,46 +88,25 @@ class SWCommandUtils { })); MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList)); MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), createMapper(StringBuilder::new, Collections::singletonList)); - MAPPER_FUNCTIONS.put(Player.class.getTypeName(), new TypeMapper() { - @Override - public Player map(String s) { - return Bukkit.getPlayer(s); + MAPPER_FUNCTIONS.put(Player.class.getTypeName(), createMapper(Bukkit::getPlayer, s -> { + return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + })); + MAPPER_FUNCTIONS.put(GameMode.class.getTypeName(), createMapper(s -> { + s = s.toLowerCase(); + if (s.equals("s") || s.equals("survival") || s.equals("0")) { + return GameMode.SURVIVAL; } - - @Override - public List tabCompletes(String s) { - return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + if (s.equals("c") || s.equals("creative") || s.equals("1")) { + return GameMode.CREATIVE; } - }); - MAPPER_FUNCTIONS.put(GameMode.class.getTypeName(), new TypeMapper() { - @Override - public GameMode map(String s) { - switch (s.toLowerCase()) { - case "s": - case "survival": - case "0": - return GameMode.SURVIVAL; - case "c": - case "creative": - case "1": - return GameMode.CREATIVE; - case "sp": - case "spectator": - case "3": - return GameMode.SPECTATOR; - case "a": - case "adventure": - case "2": - return GameMode.ADVENTURE; - } - throw new SecurityException(); + if (s.equals("sp") || s.equals("spectator") || s.equals("3")) { + return GameMode.SPECTATOR; } - - @Override - public List tabCompletes(String s) { - return Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "specator", "3", "a", "adventure", "2"); + if (s.equals("a") || s.equals("adventure") || s.equals("2")) { + return GameMode.ADVENTURE; } - }); + throw new SecurityException(); + }, s -> Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "specator", "3", "a", "adventure", "2"))); } private static void addMapper(Class clazz, Class alternativeClazz, TypeMapper mapper) { From abc48d9215ccccff06d48f2f8965874390acb948 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 08:44:41 +0100 Subject: [PATCH 35/71] Optimize SWCommandUtils --- .../de/steamwar/command/SWCommandUtils.java | 42 +++++++------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 3c3f9b1..d2fbc45 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -32,7 +32,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; -class SWCommandUtils { +public class SWCommandUtils { private SWCommandUtils() { throw new IllegalStateException("Utility Class"); @@ -62,30 +62,9 @@ class SWCommandUtils { static { addMapper(boolean.class, Boolean.class, createMapper(Boolean::parseBoolean, s -> Arrays.asList("true", "false"))); - addMapper(float.class, Float.class, createMapper(Float::parseFloat, s -> { - try { - Float.parseFloat(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - })); - addMapper(double.class, Double.class, createMapper(Double::parseDouble, s -> { - try { - Double.parseDouble(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - })); - addMapper(int.class, Integer.class, createMapper(Integer::parseInt, s -> { - try { - Integer.parseInt(s); - return Collections.singletonList(s); - } catch (NumberFormatException e) { - return Collections.emptyList(); - } - })); + addMapper(float.class, Float.class, createMapper(Float::parseFloat, numberCompleter(Float::parseFloat))); + addMapper(double.class, Double.class, createMapper(Double::parseDouble, numberCompleter(Double::parseDouble))); + addMapper(int.class, Integer.class, createMapper(Integer::parseInt, numberCompleter(Integer::parseInt))); MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList)); MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), createMapper(StringBuilder::new, Collections::singletonList)); MAPPER_FUNCTIONS.put(Player.class.getTypeName(), createMapper(Bukkit::getPlayer, s -> { @@ -127,7 +106,7 @@ class SWCommandUtils { } } - public static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, boolean varArgs, String[] subCommand) { + 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) { @@ -174,6 +153,17 @@ class SWCommandUtils { }; } + private static Function> numberCompleter(Function mapper) { + return s -> { + try { + mapper.apply(s); + return Collections.singletonList(s); + } catch (Exception e) { + return Collections.emptyList(); + } + }; + } + static T getAnnotation(Method method, Class annotation) { if (method.getAnnotations().length != 1) return null; return method.getAnnotation(annotation); From 7020d6b8f369393cc44b64fc7e5b659731ac0a75 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 08:57:37 +0100 Subject: [PATCH 36/71] Optimize SWCommand --- .../src/de/steamwar/command/SWCommand.java | 108 +++++++----------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 725f451..eac71c3 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -22,13 +22,11 @@ package de.steamwar.command; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.*; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; +import java.util.function.IntPredicate; import static de.steamwar.command.SWCommandUtils.getAnnotation; @@ -79,81 +77,63 @@ public abstract class SWCommand { Set commandMethods = new HashSet<>(); for (Method method : getClass().getDeclaredMethods()) { - addMapper(method); - addCommand(method, commandMethods); - addHelp(method); + add(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, method1, parameters) -> { + try { + method.setAccessible(true); + Object object = method.invoke(this); + SWCommandUtils.addMapper(anno.value(), (TypeMapper) object); + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); + } + }); + add(Register.class, method, i -> i == 0, true, null, (anno, method1, parameters) -> { + 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(); + } + Mapper mapper = parameter.getAnnotation(Mapper.class); + if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) { + continue; + } + String name = clazz.getTypeName(); + if (mapper != null) { + name = mapper.value(); + } + if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return; + } + commandMethods.add(method); + }); + add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, method1, parameters) -> { + commandHelpSet.add(new SubCommand(this, method)); + }); } commandMethods.forEach(method -> commandSet.add(new SubCommand(this, method))); } - private void addCommand(Method method, Set commandMethods) { - Register register = getAnnotation(method, Register.class); - if (register == null) { + private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, SWConsumer consumer) { + T anno = getAnnotation(method, annotation); + if (anno == null) { return; } Parameter[] parameters = method.getParameters(); - if (parameters.length == 0) { + if (parameterTester.test(parameters.length)) { return; } - if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) { + if (firstParameter && !CommandSender.class.isAssignableFrom(parameters[0].getType())) { 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(); - } - Mapper mapper = parameter.getAnnotation(Mapper.class); - if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) { - continue; - } - String name = clazz.getTypeName(); - if (mapper != null) { - name = mapper.value(); - } - if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return; + if (returnType != null && method.getReturnType() != returnType) { + return; } - commandMethods.add(method); + consumer.consume(anno, method, parameters); } - private void addHelp(Method method) { - RegisterHelp registerHelp = getAnnotation(method, RegisterHelp.class); - if (registerHelp == null) { - return; - } - - Parameter[] parameters = method.getParameters(); - if (parameters.length != 1) { - return; - } - if (!CommandSender.class.isAssignableFrom(parameters[0].getType())) { - return; - } - commandHelpSet.add(new SubCommand(this, method)); - } - - private void addMapper(Method method) { - Mapper mapper = getAnnotation(method, Mapper.class); - if (mapper == null) { - return; - } - - Parameter[] parameters = method.getParameters(); - if (parameters.length != 0) { - return; - } - if (method.getReturnType() != TypeMapper.class) { - return; - } - try { - method.setAccessible(true); - Object object = method.invoke(this); - SWCommandUtils.addMapper(mapper.value(), (TypeMapper) object); - } catch (Exception e) { - throw new SecurityException(e.getMessage(), e); - } + @FunctionalInterface + private interface SWConsumer { + void consume(T anno, Method method, Parameter[] parameters); } @Retention(RetentionPolicy.RUNTIME) From 5bd160b0c984ef6f9a27002dc50a8dc3ae2732b7 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 08:59:12 +0100 Subject: [PATCH 37/71] Optimize SWCommand --- .../src/de/steamwar/command/SWCommand.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index eac71c3..8c24bad 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -26,6 +26,7 @@ import java.lang.annotation.*; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; +import java.util.function.BiConsumer; import java.util.function.IntPredicate; import static de.steamwar.command.SWCommandUtils.getAnnotation; @@ -77,7 +78,7 @@ public abstract class SWCommand { Set commandMethods = new HashSet<>(); for (Method method : getClass().getDeclaredMethods()) { - add(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, method1, parameters) -> { + add(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { try { method.setAccessible(true); Object object = method.invoke(this); @@ -86,7 +87,7 @@ public abstract class SWCommand { throw new SecurityException(e.getMessage(), e); } }); - add(Register.class, method, i -> i == 0, true, null, (anno, method1, parameters) -> { + add(Register.class, method, i -> i == 0, true, null, (anno, parameters) -> { for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; Class clazz = parameter.getType(); @@ -105,14 +106,14 @@ public abstract class SWCommand { } commandMethods.add(method); }); - add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, method1, parameters) -> { + add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { commandHelpSet.add(new SubCommand(this, method)); }); } commandMethods.forEach(method -> commandSet.add(new SubCommand(this, method))); } - private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, SWConsumer consumer) { + private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, BiConsumer consumer) { T anno = getAnnotation(method, annotation); if (anno == null) { return; @@ -128,12 +129,7 @@ public abstract class SWCommand { if (returnType != null && method.getReturnType() != returnType) { return; } - consumer.consume(anno, method, parameters); - } - - @FunctionalInterface - private interface SWConsumer { - void consume(T anno, Method method, Parameter[] parameters); + consumer.accept(anno, parameters); } @Retention(RetentionPolicy.RUNTIME) From ccb63e16139f3c583a54b8c1ffbf14bfc6ecbdbe Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 09:06:21 +0100 Subject: [PATCH 38/71] Optimize SWCommand Optimize SubCommand --- .../src/de/steamwar/command/SWCommand.java | 12 ++++----- .../src/de/steamwar/command/SubCommand.java | 27 +++++-------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 8c24bad..d27e575 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -76,7 +76,6 @@ public abstract class SWCommand { } }); - Set commandMethods = new HashSet<>(); for (Method method : getClass().getDeclaredMethods()) { add(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { try { @@ -87,6 +86,11 @@ public abstract class SWCommand { throw new SecurityException(e.getMessage(), e); } }); + add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { + commandHelpSet.add(new SubCommand(this, method, anno.value())); + }); + } + for (Method method : getClass().getDeclaredMethods()) { add(Register.class, method, i -> i == 0, true, null, (anno, parameters) -> { for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; @@ -104,13 +108,9 @@ public abstract class SWCommand { } if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return; } - commandMethods.add(method); - }); - add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { - commandHelpSet.add(new SubCommand(this, method)); + commandSet.add(new SubCommand(this, method, anno.value())); }); } - commandMethods.forEach(method -> commandSet.add(new SubCommand(this, method))); } private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, BiConsumer consumer) { diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 053aae3..b807c03 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -39,21 +39,13 @@ class SubCommand { private boolean varArgs = false; private Function commandSenderFunction; - public SubCommand(SWCommand swCommand, Method method) { + public SubCommand(SWCommand swCommand, Method method, String[] subCommand) { this.swCommand = swCommand; this.method = method; Parameter[] parameters = method.getParameters(); commandSenderFunction = sender -> parameters[0].getType().cast(sender); - SWCommand.Register register = SWCommandUtils.getAnnotation(method, SWCommand.Register.class); - SWCommand.RegisterHelp registerHelp = SWCommandUtils.getAnnotation(method, SWCommand.RegisterHelp.class); - if (register != null) { - subCommand = register.value(); - } else if (registerHelp != null) { - subCommand = registerHelp.value(); - } else { - throw new SecurityException(); - } + this.subCommand = subCommand; arguments = new TypeMapper[parameters.length - 1]; for (int i = 1; i < parameters.length; i++) { @@ -71,17 +63,7 @@ class SubCommand { 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; - } - }; + arguments[i] = SWCommandUtils.createMapper(s -> SWCommandUtils.ENUM_MAPPER.apply(enumClass, s), s -> tabCompletes); continue; } @@ -112,6 +94,9 @@ class SubCommand { } List tabComplete(CommandSender commandSender, String[] args) { + if (!varArgs && args.length < arguments.length - 1) { + return Collections.emptyList(); + } List argsList = Arrays.asList(args); for (String value : subCommand) { String s = argsList.remove(0); From d0186a43d156dbc29d5a926054bb35d80af899e6 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 09:09:39 +0100 Subject: [PATCH 39/71] Optimize SWCommandUtils --- .../de/steamwar/command/SWCommandUtils.java | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index d2fbc45..0a9cb84 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -40,17 +40,9 @@ public class SWCommandUtils { static final Map> MAPPER_FUNCTIONS = new HashMap<>(); - static final TypeMapper ERROR_FUNCTION = new TypeMapper() { - @Override - public Object map(String s) { - throw new SecurityException(); - } - - @Override - public List tabCompletes(String s) { - return Collections.emptyList(); - } - }; + static final TypeMapper ERROR_FUNCTION = createMapper(s -> { + throw new SecurityException(); + }, s -> Collections.emptyList()); static final BiFunction>, String, Enum> ENUM_MAPPER = (enumClass, s) -> { Enum[] enums = enumClass.getEnumConstants(); @@ -67,23 +59,13 @@ public class SWCommandUtils { addMapper(int.class, Integer.class, createMapper(Integer::parseInt, numberCompleter(Integer::parseInt))); MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList)); MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), createMapper(StringBuilder::new, Collections::singletonList)); - MAPPER_FUNCTIONS.put(Player.class.getTypeName(), createMapper(Bukkit::getPlayer, s -> { - return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - })); + MAPPER_FUNCTIONS.put(Player.class.getTypeName(), createMapper(Bukkit::getPlayer, s -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()))); MAPPER_FUNCTIONS.put(GameMode.class.getTypeName(), createMapper(s -> { s = s.toLowerCase(); - if (s.equals("s") || s.equals("survival") || s.equals("0")) { - return GameMode.SURVIVAL; - } - if (s.equals("c") || s.equals("creative") || s.equals("1")) { - return GameMode.CREATIVE; - } - if (s.equals("sp") || s.equals("spectator") || s.equals("3")) { - return GameMode.SPECTATOR; - } - if (s.equals("a") || s.equals("adventure") || s.equals("2")) { - return GameMode.ADVENTURE; - } + if (s.equals("s") || s.equals("survival") || s.equals("0")) return GameMode.SURVIVAL; + if (s.equals("c") || s.equals("creative") || s.equals("1")) return GameMode.CREATIVE; + if (s.equals("sp") || s.equals("spectator") || s.equals("3")) return GameMode.SPECTATOR; + if (s.equals("a") || s.equals("adventure") || s.equals("2")) return GameMode.ADVENTURE; throw new SecurityException(); }, s -> Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "specator", "3", "a", "adventure", "2"))); } From 54c3c8e203d99f5680f95183a1c6758c0863bb2b Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 26 Mar 2021 09:16:01 +0100 Subject: [PATCH 40/71] Add SWCommand.enabled for enabling and disabling commands --- .../src/de/steamwar/command/SWCommand.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index d27e575..5623169 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -33,6 +33,7 @@ import static de.steamwar.command.SWCommandUtils.getAnnotation; public abstract class SWCommand { + private boolean enabled = true; private final Set commandSet = new HashSet<>(); private final Set commandHelpSet = new HashSet<>(); @@ -44,6 +45,7 @@ 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) { + if (!enabled) return false; for (SubCommand subCommand : commandSet) { if (subCommand.invoke(sender, args)) { return false; @@ -59,6 +61,7 @@ public abstract class SWCommand { @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + if (!enabled) return Collections.emptyList(); List strings = new ArrayList<>(); for (SubCommand subCommand : commandSet) { List tabCompletes = subCommand.tabComplete(sender, args); @@ -132,6 +135,14 @@ public abstract class SWCommand { consumer.accept(anno, parameters); } + protected boolean isEnabled() { + return enabled; + } + + protected void setEnabled(boolean enabled) { + this.enabled = enabled; + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) protected @interface Register { From e56d4c0e42bf45e9b1f7f0f37e80a17f961191ff Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 20:52:16 +0200 Subject: [PATCH 41/71] Fix case sensitive TabCompletes --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 0a9cb84..93f6ec0 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -47,7 +47,7 @@ public class SWCommandUtils { static final BiFunction>, String, Enum> ENUM_MAPPER = (enumClass, s) -> { Enum[] enums = enumClass.getEnumConstants(); for (Enum e : enums) { - if (e.name().equals(s)) return e; + if (e.name().equalsIgnoreCase(s)) return e; } return null; }; From 7e733fca7cb2ac3c74c589933ed328ec6c7039d4 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 22:14:52 +0200 Subject: [PATCH 42/71] Make HelpMessage more advanced --- .../src/de/steamwar/acommand/TestCommand.java | 3 ++- .../src/de/steamwar/command/SWCommand.java | 6 ++++++ .../src/de/steamwar/command/SubCommand.java | 18 ++++++++++-------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index 90800e1..7b77f97 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -36,8 +36,9 @@ public class TestCommand extends SWCommand { } // One Help Command, the first Parameter should be some kind of CommandSender + // The second argument can only be a varAgrs string of what arguments was tried to map @RegisterHelp - public void testHelp(Player player) { + public void testHelp(Player player, String... args) { player.sendMessage("This is your help message"); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 5623169..ed6c7c1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -90,6 +90,12 @@ public abstract class SWCommand { } }); add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { + if (!parameters[parameters.length - 1].isVarArgs()) { + return; + } + if (parameters[parameters.length - 1].getType().getComponentType() != String.class) { + return; + } commandHelpSet.add(new SubCommand(this, method, anno.value())); }); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index b807c03..ce98811 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -24,10 +24,7 @@ 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.Collections; -import java.util.List; +import java.util.*; import java.util.function.Function; class SubCommand { @@ -63,7 +60,7 @@ class SubCommand { for (Enum enumConstant : enumClass.getEnumConstants()) { tabCompletes.add(enumConstant.name().toLowerCase()); } - arguments[i] = SWCommandUtils.createMapper(s -> SWCommandUtils.ENUM_MAPPER.apply(enumClass, s), s -> tabCompletes); + arguments[i - 1] = SWCommandUtils.createMapper(s -> SWCommandUtils.ENUM_MAPPER.apply(enumClass, s), s -> tabCompletes); continue; } @@ -72,7 +69,7 @@ class SubCommand { name = mapper.value(); } - arguments[i] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); + arguments[i - 1] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); } } @@ -80,6 +77,9 @@ class SubCommand { if (args.length < arguments.length - 1) { return false; } + if (!varArgs && args.length > arguments.length) { + return false; + } try { Object[] objects = SWCommandUtils.generateArgumentArray(arguments, args, varArgs, subCommand); objects[0] = commandSenderFunction.apply(commandSender); @@ -97,7 +97,7 @@ class SubCommand { if (!varArgs && args.length < arguments.length - 1) { return Collections.emptyList(); } - List argsList = Arrays.asList(args); + List argsList = new LinkedList<>(Arrays.asList(args)); for (String value : subCommand) { String s = argsList.remove(0); if (argsList.isEmpty()) return Collections.singletonList(value); @@ -107,7 +107,9 @@ class SubCommand { String s = argsList.remove(0); if (argsList.isEmpty()) return argument.tabCompletes(s); try { - argument.map(s); + if (argument.map(s) == null) { + return Collections.emptyList(); + } } catch (Exception e) { return Collections.emptyList(); } From 2ad2dc29e458d997e61ac3fbd48fd35f05d8d59d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 22:20:03 +0200 Subject: [PATCH 43/71] Add SWCommand.ClassMapper --- .../src/de/steamwar/command/SWCommand.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index ed6c7c1..3b4b6e7 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -89,6 +89,15 @@ public abstract class SWCommand { throw new SecurityException(e.getMessage(), e); } }); + add(ClassMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { + try { + method.setAccessible(true); + Object object = method.invoke(this); + SWCommandUtils.addMapper(anno.value().getTypeName(), (TypeMapper) object); + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); + } + }); add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { if (!parameters[parameters.length - 1].isVarArgs()) { return; @@ -167,4 +176,11 @@ public abstract class SWCommand { String value(); } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + protected @interface ClassMapper { + Class value(); + } + } From 9c7cea96d4a461b05c3b512da1a2585d5922853a Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 22:28:33 +0200 Subject: [PATCH 44/71] Add SWCommand.LocalMapper only defined in current class scope overrides any global mapper for this class only --- .../src/de/steamwar/command/SWCommand.java | 19 +++++++++++++++++-- .../src/de/steamwar/command/SubCommand.java | 15 +++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 3b4b6e7..ac3f65d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -36,6 +36,7 @@ public abstract class SWCommand { private boolean enabled = true; private final Set commandSet = new HashSet<>(); private final Set commandHelpSet = new HashSet<>(); + private final Map> localTypeMapper = new HashMap<>(); protected SWCommand(String command) { this(command, new String[0]); @@ -64,7 +65,7 @@ public abstract class SWCommand { if (!enabled) return Collections.emptyList(); List strings = new ArrayList<>(); for (SubCommand subCommand : commandSet) { - List tabCompletes = subCommand.tabComplete(sender, args); + List tabCompletes = subCommand.tabComplete(args); if (tabCompletes != null) { strings.addAll(tabCompletes); } @@ -98,6 +99,15 @@ public abstract class SWCommand { throw new SecurityException(e.getMessage(), e); } }); + add(LocalMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { + try { + method.setAccessible(true); + Object object = method.invoke(this); + localTypeMapper.put(anno.value(), (TypeMapper) object); + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); + } + }); add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { if (!parameters[parameters.length - 1].isVarArgs()) { return; @@ -176,11 +186,16 @@ public abstract class SWCommand { String value(); } - @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) protected @interface ClassMapper { Class value(); } + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + protected @interface LocalMapper { + String value(); + } + } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index ce98811..307b36e 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -37,6 +37,10 @@ class SubCommand { private Function commandSenderFunction; public SubCommand(SWCommand swCommand, Method method, String[] subCommand) { + this(swCommand, method, subCommand, new HashMap<>()); + } + + public SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper) { this.swCommand = swCommand; this.method = method; @@ -54,7 +58,7 @@ class SubCommand { } SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); - if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName())) { + if (clazz.isEnum() && mapper == null && !SWCommandUtils.MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) { Class> enumClass = (Class>) clazz; List tabCompletes = new ArrayList<>(); for (Enum enumConstant : enumClass.getEnumConstants()) { @@ -68,8 +72,11 @@ class SubCommand { if (mapper != null) { name = mapper.value(); } - - arguments[i - 1] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); + if (localTypeMapper.containsKey(name)) { + arguments[i - 1] = localTypeMapper.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); + } else { + arguments[i - 1] = SWCommandUtils.MAPPER_FUNCTIONS.getOrDefault(name, SWCommandUtils.ERROR_FUNCTION); + } } } @@ -93,7 +100,7 @@ class SubCommand { return true; } - List tabComplete(CommandSender commandSender, String[] args) { + List tabComplete(String[] args) { if (!varArgs && args.length < arguments.length - 1) { return Collections.emptyList(); } From 529b3daf6c7df06e2819db347a3e819594610be6 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 22:35:31 +0200 Subject: [PATCH 45/71] Simplify SWCommand Add SWCommandUtils.addMapper with class --- .../src/de/steamwar/command/SWCommand.java | 42 ++++++++----------- .../de/steamwar/command/SWCommandUtils.java | 4 ++ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index ac3f65d..47b4253 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -81,32 +81,14 @@ public abstract class SWCommand { }); for (Method method : getClass().getDeclaredMethods()) { - add(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { - try { - method.setAccessible(true); - Object object = method.invoke(this); - SWCommandUtils.addMapper(anno.value(), (TypeMapper) object); - } catch (Exception e) { - throw new SecurityException(e.getMessage(), e); - } + addMapper(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { + SWCommandUtils.addMapper(anno.value(), typeMapper); }); - add(ClassMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { - try { - method.setAccessible(true); - Object object = method.invoke(this); - SWCommandUtils.addMapper(anno.value().getTypeName(), (TypeMapper) object); - } catch (Exception e) { - throw new SecurityException(e.getMessage(), e); - } + addMapper(ClassMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { + SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); }); - add(LocalMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, parameters) -> { - try { - method.setAccessible(true); - Object object = method.invoke(this); - localTypeMapper.put(anno.value(), (TypeMapper) object); - } catch (Exception e) { - throw new SecurityException(e.getMessage(), e); - } + addMapper(LocalMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { + localTypeMapper.put(anno.value(), typeMapper); }); add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { if (!parameters[parameters.length - 1].isVarArgs()) { @@ -160,6 +142,18 @@ public abstract class SWCommand { consumer.accept(anno, 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); + Object object = method.invoke(this); + consumer.accept(anno, (TypeMapper) object); + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); + } + }); + } + protected boolean isEnabled() { return enabled; } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 93f6ec0..deb4523 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -116,6 +116,10 @@ public class SWCommandUtils { return arguments; } + public static void addMapper(Class clazz, TypeMapper mapper) { + addMapper(clazz.getTypeName(), mapper); + } + public static void addMapper(String name, TypeMapper mapper) { if (MAPPER_FUNCTIONS.containsKey(name)) return; MAPPER_FUNCTIONS.put(name, mapper); From 8be46cd7bc4685851cf1f9718ca61182c9c2fe9e Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 22:51:27 +0200 Subject: [PATCH 46/71] Add more capabilities to TypeMapper.tabCompletes --- .../src/de/steamwar/command/SWCommand.java | 6 ++---- .../src/de/steamwar/command/SWCommandUtils.java | 17 ++++++++++++++++- .../src/de/steamwar/command/SubCommand.java | 6 +++--- .../src/de/steamwar/command/TypeMapper.java | 4 +++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 47b4253..0fff614 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -29,8 +29,6 @@ import java.util.*; import java.util.function.BiConsumer; import java.util.function.IntPredicate; -import static de.steamwar.command.SWCommandUtils.getAnnotation; - public abstract class SWCommand { private boolean enabled = true; @@ -65,7 +63,7 @@ public abstract class SWCommand { if (!enabled) return Collections.emptyList(); List strings = new ArrayList<>(); for (SubCommand subCommand : commandSet) { - List tabCompletes = subCommand.tabComplete(args); + List tabCompletes = subCommand.tabComplete(sender, args); if (tabCompletes != null) { strings.addAll(tabCompletes); } @@ -124,7 +122,7 @@ public abstract class SWCommand { } private void add(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, BiConsumer consumer) { - T anno = getAnnotation(method, annotation); + T anno = SWCommandUtils.getAnnotation(method, annotation); if (anno == null) { return; } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index deb4523..dac72ea 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -22,6 +22,7 @@ package de.steamwar.command; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.lang.annotation.Annotation; @@ -133,12 +134,26 @@ public class SWCommandUtils { } @Override - public List tabCompletes(String s) { + public List tabCompletes(CommandSender commandSender, String s) { return tabCompleter.apply(s); } }; } + public static TypeMapper createMapper(Function mapper, BiFunction> tabCompleter) { + return new TypeMapper() { + @Override + public T map(String s) { + return mapper.apply(s); + } + + @Override + public List tabCompletes(CommandSender commandSender, String s) { + return tabCompleter.apply(commandSender, s); + } + }; + } + private static Function> numberCompleter(Function mapper) { return s -> { try { diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 307b36e..b1bb15c 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -100,7 +100,7 @@ class SubCommand { return true; } - List tabComplete(String[] args) { + List tabComplete(CommandSender commandSender, String[] args) { if (!varArgs && args.length < arguments.length - 1) { return Collections.emptyList(); } @@ -112,7 +112,7 @@ class SubCommand { } for (TypeMapper argument : arguments) { String s = argsList.remove(0); - if (argsList.isEmpty()) return argument.tabCompletes(s); + if (argsList.isEmpty()) return argument.tabCompletes(commandSender, s); try { if (argument.map(s) == null) { return Collections.emptyList(); @@ -124,7 +124,7 @@ class SubCommand { if (varArgs && !argsList.isEmpty()) { while (!argsList.isEmpty()) { String s = argsList.remove(0); - if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(s); + if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, s); try { arguments[arguments.length - 1].map(s); } catch (Exception e) { diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java index c9f34e4..f1b5e16 100644 --- a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java +++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java @@ -19,10 +19,12 @@ package de.steamwar.command; +import org.bukkit.command.CommandSender; + import java.util.List; public interface TypeMapper { T map(String s); - List tabCompletes(String s); + List tabCompletes(CommandSender commandSender, String s); } From 9436616440cca0fdaa768caf65b29030fbf5f9f8 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 22:57:00 +0200 Subject: [PATCH 47/71] Fix design stuff --- .../src/de/steamwar/command/SWCommand.java | 1 - .../src/de/steamwar/command/SWCommandUtils.java | 13 +------------ .../src/de/steamwar/command/SubCommand.java | 1 - 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 0fff614..8b4f663 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -189,5 +189,4 @@ public abstract class SWCommand { protected @interface LocalMapper { String value(); } - } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index dac72ea..981b5ca 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -127,17 +127,7 @@ public class SWCommandUtils { } public static TypeMapper createMapper(Function mapper, Function> tabCompleter) { - return new TypeMapper() { - @Override - public T map(String s) { - return mapper.apply(s); - } - - @Override - public List tabCompletes(CommandSender commandSender, String s) { - return tabCompleter.apply(s); - } - }; + return createMapper(mapper, (commandSender, s) -> tabCompleter.apply(s)); } public static TypeMapper createMapper(Function mapper, BiFunction> tabCompleter) { @@ -169,5 +159,4 @@ public class SWCommandUtils { if (method.getAnnotations().length != 1) return null; return method.getAnnotation(annotation); } - } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index b1bb15c..e0088ec 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -134,5 +134,4 @@ class SubCommand { } return Collections.emptyList(); } - } From 7bc47a8997b71edff976ab2ee0a32af72567ae9d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 29 Mar 2021 23:06:30 +0200 Subject: [PATCH 48/71] Add TypeMapper.tabCompletes with previous TabCompletes --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 2 +- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 4 ++-- SpigotCore_Main/src/de/steamwar/command/TypeMapper.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 981b5ca..2ddf34d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -138,7 +138,7 @@ public class SWCommandUtils { } @Override - public List tabCompletes(CommandSender commandSender, String s) { + public List tabCompletes(CommandSender commandSender, String[] previous, String s) { return tabCompleter.apply(commandSender, s); } }; diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index e0088ec..747e602 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -112,7 +112,7 @@ class SubCommand { } for (TypeMapper argument : arguments) { String s = argsList.remove(0); - if (argsList.isEmpty()) return argument.tabCompletes(commandSender, s); + if (argsList.isEmpty()) return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { if (argument.map(s) == null) { return Collections.emptyList(); @@ -124,7 +124,7 @@ class SubCommand { if (varArgs && !argsList.isEmpty()) { while (!argsList.isEmpty()) { String s = argsList.remove(0); - if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, s); + if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { arguments[arguments.length - 1].map(s); } catch (Exception e) { diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java index f1b5e16..90dbf1e 100644 --- a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java +++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java @@ -26,5 +26,5 @@ import java.util.List; public interface TypeMapper { T map(String s); - List tabCompletes(CommandSender commandSender, String s); + List tabCompletes(CommandSender commandSender, String[] previousArguments, String s); } From 6ac208dc56c0e95b206efb478c7c2de666b367be Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 08:21:55 +0200 Subject: [PATCH 49/71] Removed cluttered Annotations --- .../src/de/steamwar/acommand/TestCommand.java | 7 +++-- .../src/de/steamwar/command/SWCommand.java | 31 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index 7b77f97..df35220 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -22,6 +22,7 @@ package de.steamwar.acommand; import de.steamwar.command.SWCommand; import de.steamwar.command.TypeMapper; import org.bukkit.Material; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.Arrays; @@ -37,7 +38,7 @@ public class TestCommand extends SWCommand { // One Help Command, the first Parameter should be some kind of CommandSender // The second argument can only be a varAgrs string of what arguments was tried to map - @RegisterHelp + @Register(help = true) public void testHelp(Player player, String... args) { player.sendMessage("This is your help message"); } @@ -65,14 +66,14 @@ public class TestCommand extends SWCommand { .map(Material::name) .map(String::toLowerCase) .collect(Collectors.toList()); - return new TypeMapper() { + return new TypeMapper<>() { @Override public Material map(String s) { return Material.valueOf(s.toUpperCase()); } @Override - public List tabCompletes(String s) { + public List tabCompletes(CommandSender commandSender, String[] previous, String s) { return tabCompletes; } }; diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 8b4f663..5488b18 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -80,15 +80,19 @@ public abstract class SWCommand { for (Method method : getClass().getDeclaredMethods()) { addMapper(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { - SWCommandUtils.addMapper(anno.value(), typeMapper); + if (anno.local()) { + localTypeMapper.put(anno.value(), typeMapper); + } else { + SWCommandUtils.addMapper(anno.value(), typeMapper); + } }); addMapper(ClassMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); }); - addMapper(LocalMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { - localTypeMapper.put(anno.value(), typeMapper); - }); - add(RegisterHelp.class, method, i -> i != 1, true, null, (anno, parameters) -> { + add(Register.class, method, i -> i != 2, true, null, (anno, parameters) -> { + if (!anno.help()) { + return; + } if (!parameters[parameters.length - 1].isVarArgs()) { return; } @@ -100,6 +104,9 @@ public abstract class SWCommand { } for (Method method : getClass().getDeclaredMethods()) { add(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(); @@ -164,18 +171,14 @@ public abstract class SWCommand { @Target({ElementType.METHOD}) protected @interface Register { String[] value() default {}; - } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - protected @interface RegisterHelp { - String[] value() default {}; + boolean help() default false; } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER, ElementType.METHOD}) protected @interface Mapper { String value(); + boolean local() default false; } @Retention(RetentionPolicy.RUNTIME) @@ -183,10 +186,4 @@ public abstract class SWCommand { protected @interface ClassMapper { Class value(); } - - @Retention(RetentionPolicy.RUNTIME) - @Target({ElementType.METHOD}) - protected @interface LocalMapper { - String value(); - } } From db1198bdd94961a6e3a396534369993287bac03b Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 08:24:16 +0200 Subject: [PATCH 50/71] Fix TestCommand --- SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index df35220..50901f1 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -37,7 +37,7 @@ public class TestCommand extends SWCommand { } // One Help Command, the first Parameter should be some kind of CommandSender - // The second argument can only be a varAgrs string of what arguments was tried to map + // The second argument can only be a varAgrs string of what arguments were tried to map @Register(help = true) public void testHelp(Player player, String... args) { player.sendMessage("This is your help message"); @@ -66,7 +66,7 @@ public class TestCommand extends SWCommand { .map(Material::name) .map(String::toLowerCase) .collect(Collectors.toList()); - return new TypeMapper<>() { + return new TypeMapper() { @Override public Material map(String s) { return Material.valueOf(s.toUpperCase()); From db8d9697e6193973998f244e81419bd89b39a95c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 08:28:08 +0200 Subject: [PATCH 51/71] Simplify double not on SWCommand.add --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 5488b18..d1bcdb1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -79,7 +79,7 @@ public abstract class SWCommand { }); for (Method method : getClass().getDeclaredMethods()) { - addMapper(Mapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { + addMapper(Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { if (anno.local()) { localTypeMapper.put(anno.value(), typeMapper); } else { @@ -89,7 +89,7 @@ public abstract class SWCommand { addMapper(ClassMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); }); - add(Register.class, method, i -> i != 2, true, null, (anno, parameters) -> { + add(Register.class, method, i -> i == 2, true, null, (anno, parameters) -> { if (!anno.help()) { return; } @@ -103,7 +103,7 @@ public abstract class SWCommand { }); } for (Method method : getClass().getDeclaredMethods()) { - add(Register.class, method, i -> i == 0, true, null, (anno, parameters) -> { + add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> { if (anno.help()) { return; } @@ -135,7 +135,7 @@ public abstract class SWCommand { } Parameter[] parameters = method.getParameters(); - if (parameterTester.test(parameters.length)) { + if (!parameterTester.test(parameters.length)) { return; } if (firstParameter && !CommandSender.class.isAssignableFrom(parameters[0].getType())) { From 1d1d95b78fb75ad98d46fea7037e46f6739a26d1 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 08:36:06 +0200 Subject: [PATCH 52/71] Fix SubCommand varAgrs tabComplete --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 747e602..640bdbf 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -19,6 +19,7 @@ package de.steamwar.command; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.lang.reflect.InvocationTargetException; @@ -26,6 +27,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; import java.util.function.Function; +import java.util.logging.Level; class SubCommand { @@ -95,6 +97,7 @@ class SubCommand { } catch (IllegalArgumentException | IllegalAccessException e) { throw new SecurityException(e.getMessage(), e); } catch (InvocationTargetException | RuntimeException e) { + Bukkit.getLogger().log(Level.INFO, e.getMessage(), e); return false; } return true; @@ -126,7 +129,9 @@ class SubCommand { String s = argsList.remove(0); if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { - arguments[arguments.length - 1].map(s); + if (arguments[arguments.length - 1].map(s) == null) { + return Collections.emptyList(); + } } catch (Exception e) { return Collections.emptyList(); } From 35758f10006dd8d006c0f8786badc722143f5a5c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 08:55:18 +0200 Subject: [PATCH 53/71] Simplify SubCommand to conform to TypeMapper.tabComplete Add messages to why it did not work --- .../src/de/steamwar/command/SWCommand.java | 12 +++++++++++- .../src/de/steamwar/command/SubCommand.java | 18 +++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index d1bcdb1..2cd1a0a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -19,6 +19,7 @@ package de.steamwar.command; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -28,6 +29,7 @@ import java.lang.reflect.Parameter; import java.util.*; import java.util.function.BiConsumer; import java.util.function.IntPredicate; +import java.util.logging.Level; public abstract class SWCommand { @@ -94,9 +96,11 @@ public abstract class SWCommand { return; } if (!parameters[parameters.length - 1].isVarArgs()) { + Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters as last Argument"); return; } 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; } commandHelpSet.add(new SubCommand(this, method, anno.value())); @@ -121,7 +125,10 @@ public abstract class SWCommand { if (mapper != null) { name = mapper.value(); } - if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) return; + if (!SWCommandUtils.MAPPER_FUNCTIONS.containsKey(name)) { + Bukkit.getLogger().log(Level.WARNING, "The parameter '" + parameter.toString() + "' is using an unsupported Mapper of type '" + name + "'"); + return; + } } commandSet.add(new SubCommand(this, method, anno.value())); }); @@ -136,12 +143,15 @@ public abstract class SWCommand { Parameter[] parameters = method.getParameters(); if (!parameterTester.test(parameters.length)) { + Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking parameters or has too many"); return; } if (firstParameter && !CommandSender.class.isAssignableFrom(parameters[0].getType())) { + Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' 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.toString() + "' is lacking the desired return type '" + returnType.getTypeName() + "'"); return; } consumer.accept(anno, parameters); diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 640bdbf..8321196 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -94,9 +94,9 @@ class SubCommand { objects[0] = commandSenderFunction.apply(commandSender); method.setAccessible(true); method.invoke(swCommand, objects); - } catch (IllegalArgumentException | IllegalAccessException e) { + } catch (IllegalAccessException | RuntimeException e) { throw new SecurityException(e.getMessage(), e); - } catch (InvocationTargetException | RuntimeException e) { + } catch (InvocationTargetException e) { Bukkit.getLogger().log(Level.INFO, e.getMessage(), e); return false; } @@ -105,23 +105,23 @@ class SubCommand { List tabComplete(CommandSender commandSender, String[] args) { if (!varArgs && args.length < arguments.length - 1) { - return Collections.emptyList(); + return null; } List argsList = new LinkedList<>(Arrays.asList(args)); for (String value : subCommand) { String s = argsList.remove(0); if (argsList.isEmpty()) return Collections.singletonList(value); - if (!value.equals(s)) return Collections.emptyList(); + if (!value.equals(s)) return null; } for (TypeMapper argument : arguments) { String s = argsList.remove(0); if (argsList.isEmpty()) return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { if (argument.map(s) == null) { - return Collections.emptyList(); + return null; } } catch (Exception e) { - return Collections.emptyList(); + return null; } } if (varArgs && !argsList.isEmpty()) { @@ -130,13 +130,13 @@ class SubCommand { if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { if (arguments[arguments.length - 1].map(s) == null) { - return Collections.emptyList(); + return null; } } catch (Exception e) { - return Collections.emptyList(); + return null; } } } - return Collections.emptyList(); + return null; } } From 50b039e6dc592c7c0a41647e9a09036d360ee7e5 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 09:08:04 +0200 Subject: [PATCH 54/71] Add SWCommand.unregister --- .../src/de/steamwar/command/SWCommand.java | 29 +++++++++---------- .../de/steamwar/command/SWCommandUtils.java | 10 +++++++ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 2cd1a0a..30da3ec 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -33,9 +33,9 @@ import java.util.logging.Level; public abstract class SWCommand { - private boolean enabled = true; - private final Set commandSet = new HashSet<>(); - private final Set commandHelpSet = new HashSet<>(); + private final Command command; + private final LinkedList commandSet = new LinkedList<>(); + private final LinkedList commandHelpSet = new LinkedList<>(); private final Map> localTypeMapper = new HashMap<>(); protected SWCommand(String command) { @@ -43,10 +43,9 @@ public abstract class SWCommand { } protected SWCommand(String command, String... aliases) { - SWCommandUtils.commandMap.register("steamwar", new Command(command, "", "/" + command, Arrays.asList(aliases)) { + this.command = new Command(command, "", "/" + command, Arrays.asList(aliases)) { @Override public boolean execute(CommandSender sender, String alias, String[] args) { - if (!enabled) return false; for (SubCommand subCommand : commandSet) { if (subCommand.invoke(sender, args)) { return false; @@ -62,7 +61,6 @@ public abstract class SWCommand { @Override public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { - if (!enabled) return Collections.emptyList(); List strings = new ArrayList<>(); for (SubCommand subCommand : commandSet) { List tabCompletes = subCommand.tabComplete(sender, args); @@ -78,7 +76,8 @@ public abstract class SWCommand { } return strings; } - }); + }; + SWCommandUtils.commandMap.register("steamwar", this.command); for (Method method : getClass().getDeclaredMethods()) { addMapper(Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { @@ -103,7 +102,7 @@ public abstract class SWCommand { Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument"); return; } - commandHelpSet.add(new SubCommand(this, method, anno.value())); + commandHelpSet.addLast(new SubCommand(this, method, anno.value())); }); } for (Method method : getClass().getDeclaredMethods()) { @@ -130,7 +129,7 @@ public abstract class SWCommand { return; } } - commandSet.add(new SubCommand(this, method, anno.value())); + commandSet.addLast(new SubCommand(this, method, anno.value())); }); } } @@ -169,12 +168,12 @@ public abstract class SWCommand { }); } - protected boolean isEnabled() { - return enabled; - } - - protected void setEnabled(boolean enabled) { - this.enabled = enabled; + protected void unregister() { + SWCommandUtils.knownCommandMap.remove(command.getName()); + for (String alias : command.getAliases()) { + SWCommandUtils.knownCommandMap.remove(alias); + } + command.unregister(SWCommandUtils.commandMap); } @Retention(RetentionPolicy.RUNTIME) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 2ddf34d..b97db6d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -21,6 +21,7 @@ package de.steamwar.command; import org.bukkit.Bukkit; import org.bukkit.GameMode; +import org.bukkit.command.Command; import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -77,6 +78,7 @@ public class SWCommandUtils { } static final CommandMap commandMap; + static final Map knownCommandMap; static { try { @@ -87,6 +89,14 @@ public class SWCommandUtils { Bukkit.shutdown(); throw new SecurityException("Oh shit. Commands cannot be registered.", exception); } + try { + final Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands"); + knownCommandsField.setAccessible(true); + knownCommandMap = (Map) knownCommandsField.get(commandMap); + } catch (NoSuchFieldException | IllegalAccessException exception) { + Bukkit.shutdown(); + throw new SecurityException("Oh shit. Commands cannot be registered.", exception); + } } static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, boolean varArgs, String[] subCommand) { From 5a2c06232df4371a41fb5d5dcf859a46bfb13daf Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 09:21:28 +0200 Subject: [PATCH 55/71] Remove SWCommandUtils StringBuilder support as Mapper --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 2 ++ SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 30da3ec..47b6971 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -180,6 +180,7 @@ public abstract class SWCommand { @Target({ElementType.METHOD}) protected @interface Register { String[] value() default {}; + boolean help() default false; } @@ -187,6 +188,7 @@ public abstract class SWCommand { @Target({ElementType.PARAMETER, ElementType.METHOD}) protected @interface Mapper { String value(); + boolean local() default false; } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index b97db6d..8cd20fe 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -60,7 +60,6 @@ public class SWCommandUtils { addMapper(double.class, Double.class, createMapper(Double::parseDouble, numberCompleter(Double::parseDouble))); addMapper(int.class, Integer.class, createMapper(Integer::parseInt, numberCompleter(Integer::parseInt))); MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList)); - MAPPER_FUNCTIONS.put(StringBuilder.class.getTypeName(), createMapper(StringBuilder::new, Collections::singletonList)); MAPPER_FUNCTIONS.put(Player.class.getTypeName(), createMapper(Bukkit::getPlayer, s -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()))); MAPPER_FUNCTIONS.put(GameMode.class.getTypeName(), createMapper(s -> { s = s.toLowerCase(); From 07f401c2e1077987e3e6f77e689d746d28a01892 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 09:23:38 +0200 Subject: [PATCH 56/71] Simplify SubCommand.invoke with catch clause --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 8321196..7838108 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -94,11 +94,8 @@ class SubCommand { objects[0] = commandSenderFunction.apply(commandSender); method.setAccessible(true); method.invoke(swCommand, objects); - } catch (IllegalAccessException | RuntimeException e) { + } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) { throw new SecurityException(e.getMessage(), e); - } catch (InvocationTargetException e) { - Bukkit.getLogger().log(Level.INFO, e.getMessage(), e); - return false; } return true; } From 173361e1be44f560c27cf3544c159c167023a2ea Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 10:01:28 +0200 Subject: [PATCH 57/71] Add SWCommand.register --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 47b6971..51353a9 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -77,7 +77,7 @@ public abstract class SWCommand { return strings; } }; - SWCommandUtils.commandMap.register("steamwar", this.command); + register(); for (Method method : getClass().getDeclaredMethods()) { addMapper(Mapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { @@ -176,6 +176,10 @@ public abstract class SWCommand { command.unregister(SWCommandUtils.commandMap); } + protected void register() { + SWCommandUtils.commandMap.register("steamwar", this.command); + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) protected @interface Register { From e7beaa2b0f637564f9d18cbd6d14fa3dca6cec64 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 10:10:21 +0200 Subject: [PATCH 58/71] Update SWCommand list --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 51353a9..70e7443 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -34,8 +34,8 @@ import java.util.logging.Level; public abstract class SWCommand { private final Command command; - private final LinkedList commandSet = new LinkedList<>(); - private final LinkedList commandHelpSet = new LinkedList<>(); + private final List commandSet = new ArrayList<>(); + private final List commandHelpSet = new ArrayList<>(); private final Map> localTypeMapper = new HashMap<>(); protected SWCommand(String command) { @@ -102,7 +102,7 @@ public abstract class SWCommand { Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters of type '" + String.class.getTypeName() + "' as last Argument"); return; } - commandHelpSet.addLast(new SubCommand(this, method, anno.value())); + commandHelpSet.add(new SubCommand(this, method, anno.value())); }); } for (Method method : getClass().getDeclaredMethods()) { @@ -129,7 +129,7 @@ public abstract class SWCommand { return; } } - commandSet.addLast(new SubCommand(this, method, anno.value())); + commandSet.add(new SubCommand(this, method, anno.value())); }); } } From a1651e896f2e8a61e8b49b0ed065d524ba0f43d3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 12:03:48 +0200 Subject: [PATCH 59/71] Sort SWCommand.commandSet by subCommand length Sort SWCommand.commandHelpSet by subCommand length --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 3 +++ SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 70e7443..3aa9668 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -131,6 +131,9 @@ public abstract class SWCommand { } commandSet.add(new SubCommand(this, method, anno.value())); }); + + commandSet.sort(Comparator.comparingInt(o -> -o.subCommand.length)); + commandHelpSet.sort(Comparator.comparingInt(o -> -o.subCommand.length)); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 7838108..f299359 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -19,7 +19,6 @@ package de.steamwar.command; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.lang.reflect.InvocationTargetException; @@ -27,13 +26,12 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; import java.util.function.Function; -import java.util.logging.Level; class SubCommand { private SWCommand swCommand; private Method method; - private String[] subCommand; + String[] subCommand; private TypeMapper[] arguments; private boolean varArgs = false; private Function commandSenderFunction; From b08855f000cec3e2af8047ef84c1e4f7ba2f28df Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 13:40:46 +0200 Subject: [PATCH 60/71] Fix SWCommandUtils.knownCommandMap --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 8cd20fe..b8c2c8c 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -24,6 +24,7 @@ import org.bukkit.GameMode; import org.bukkit.command.Command; import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; +import org.bukkit.command.SimpleCommandMap; import org.bukkit.entity.Player; import java.lang.annotation.Annotation; @@ -89,7 +90,7 @@ public class SWCommandUtils { throw new SecurityException("Oh shit. Commands cannot be registered.", exception); } try { - final Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands"); + final Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); knownCommandsField.setAccessible(true); knownCommandMap = (Map) knownCommandsField.get(commandMap); } catch (NoSuchFieldException | IllegalAccessException exception) { From c9e8b31aa4c5b57d313f1793f4c8d74dbf7c2abe Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 13:50:16 +0200 Subject: [PATCH 61/71] Fix SWCommand add HelpRegisters --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 3aa9668..cc963a1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -87,13 +87,16 @@ public abstract class SWCommand { SWCommandUtils.addMapper(anno.value(), typeMapper); } }); - addMapper(ClassMapper.class, method, i -> i != 0, false, TypeMapper.class, (anno, typeMapper) -> { + addMapper(ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); }); - add(Register.class, method, i -> i == 2, true, null, (anno, parameters) -> { + add(Register.class, method, i -> i > 2, 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"); return; From 501803b05cb16da308245915e0b6bc24f6ac74ba Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 13:54:53 +0200 Subject: [PATCH 62/71] Fix SWCommand add HelpRegisters --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index cc963a1..8070f7d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -90,7 +90,7 @@ public abstract class SWCommand { addMapper(ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); }); - add(Register.class, method, i -> i > 2, true, null, (anno, parameters) -> { + add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> { if (!anno.help()) { return; } From 2bb7a435c3ef2a4ea7856e3f3752e11c13791460 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 14:06:54 +0200 Subject: [PATCH 63/71] Add CommandParseException (Workflow Exception) --- .../command/CommandParseException.java | 42 +++++++++++++++++++ .../de/steamwar/command/SWCommandUtils.java | 6 +-- .../src/de/steamwar/command/SubCommand.java | 4 ++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/command/CommandParseException.java diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java b/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java new file mode 100644 index 0000000..b47cace --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java @@ -0,0 +1,42 @@ +/* + * 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 class CommandParseException extends Exception { + + public CommandParseException() { + } + + public CommandParseException(String message) { + super(message); + } + + public CommandParseException(String message, Throwable cause) { + super(message, cause); + } + + public CommandParseException(Throwable cause) { + super(cause); + } + + public CommandParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index b8c2c8c..e3b499a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -99,12 +99,12 @@ public class SWCommandUtils { } } - static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, boolean varArgs, String[] subCommand) { + static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, boolean varArgs, String[] subCommand) throws CommandParseException { Object[] arguments = new Object[parameters.length + 1]; int index = 0; while (index < subCommand.length) { if (!args[index].equals(subCommand[index])) { - throw new SecurityException(); + throw new CommandParseException(); } index++; } @@ -112,7 +112,7 @@ public class SWCommandUtils { 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(); + throw new CommandParseException(); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index f299359..1d23505 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -19,6 +19,7 @@ package de.steamwar.command; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.lang.reflect.InvocationTargetException; @@ -26,6 +27,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; import java.util.function.Function; +import java.util.logging.Level; class SubCommand { @@ -94,6 +96,8 @@ class SubCommand { method.invoke(swCommand, objects); } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) { throw new SecurityException(e.getMessage(), e); + } catch (CommandParseException e) { + return false; } return true; } From a7bf487336677dc1f8ab118574988f20f723f35d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 14:31:52 +0200 Subject: [PATCH 64/71] Add SubCommand.varArgType Add SWCommandUtils varArg capabilities --- .../de/steamwar/command/SWCommandUtils.java | 22 +++++++++++++------ .../src/de/steamwar/command/SubCommand.java | 14 +++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index e3b499a..464517d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -28,6 +28,7 @@ import org.bukkit.command.SimpleCommandMap; import org.bukkit.entity.Player; import java.lang.annotation.Annotation; +import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; @@ -99,7 +100,7 @@ public class SWCommandUtils { } } - static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, boolean varArgs, String[] subCommand) throws CommandParseException { + static Object[] generateArgumentArray(TypeMapper[] parameters, String[] args, Class varArgType, String[] subCommand) throws CommandParseException { Object[] arguments = new Object[parameters.length + 1]; int index = 0; while (index < subCommand.length) { @@ -109,19 +110,26 @@ public class SWCommandUtils { index++; } - for (int i = 0; i < parameters.length - (varArgs ? 1 : 0); i++) { - arguments[i + 1] = parameters[i].map(args[index++]); + for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { + arguments[i + 1] = parameters[i].map(args[index]); + index++; if (arguments[i + 1] == null) { throw new CommandParseException(); } } - if (varArgs) { - Object[] varArgument = new Object[args.length - parameters.length + 2]; + if (varArgType != null) { + int length = args.length - parameters.length + 1; + Object varArgument = Array.newInstance(varArgType, length); arguments[arguments.length - 1] = varArgument; - for (int i = 0; i < varArgument.length; i++) { - varArgument[i] = parameters[parameters.length - 1].map(args[index++]); + for (int i = 0; i < length; i++) { + Object value = parameters[parameters.length - 1].map(args[index]); + if (value == null) { + throw new CommandParseException(); + } + Array.set(varArgument, i, value); + index++; } } return arguments; diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 1d23505..ad359a3 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -19,7 +19,6 @@ package de.steamwar.command; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.lang.reflect.InvocationTargetException; @@ -27,7 +26,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; import java.util.function.Function; -import java.util.logging.Level; class SubCommand { @@ -35,8 +33,8 @@ class SubCommand { private Method method; String[] subCommand; private TypeMapper[] arguments; - private boolean varArgs = false; private Function commandSenderFunction; + private Class varArgType = null; public SubCommand(SWCommand swCommand, Method method, String[] subCommand) { this(swCommand, method, subCommand, new HashMap<>()); @@ -55,8 +53,8 @@ class SubCommand { Parameter parameter = parameters[i]; Class clazz = parameter.getType(); if (parameter.isVarArgs()) { - varArgs = true; clazz = clazz.getComponentType(); + varArgType = clazz; } SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); @@ -86,11 +84,11 @@ class SubCommand { if (args.length < arguments.length - 1) { return false; } - if (!varArgs && args.length > arguments.length) { + if (varArgType == null && args.length > arguments.length) { return false; } try { - Object[] objects = SWCommandUtils.generateArgumentArray(arguments, args, varArgs, subCommand); + Object[] objects = SWCommandUtils.generateArgumentArray(arguments, args, varArgType, subCommand); objects[0] = commandSenderFunction.apply(commandSender); method.setAccessible(true); method.invoke(swCommand, objects); @@ -103,7 +101,7 @@ class SubCommand { } List tabComplete(CommandSender commandSender, String[] args) { - if (!varArgs && args.length < arguments.length - 1) { + if (varArgType == null && args.length < arguments.length - 1) { return null; } List argsList = new LinkedList<>(Arrays.asList(args)); @@ -123,7 +121,7 @@ class SubCommand { return null; } } - if (varArgs && !argsList.isEmpty()) { + if (varArgType != null && !argsList.isEmpty()) { while (!argsList.isEmpty()) { String s = argsList.remove(0); if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); From ce2cd3d1bf75545ed8c945140a3295073abb3ad2 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 16:08:51 +0200 Subject: [PATCH 65/71] Fix varArgs, fix help --- .../src/de/steamwar/command/SWCommand.java | 11 ++++- .../de/steamwar/command/SWCommandUtils.java | 41 +++++++++++-------- .../src/de/steamwar/command/SubCommand.java | 10 ++--- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 8070f7d..cbfe7a1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -135,7 +135,16 @@ public abstract class SWCommand { commandSet.add(new SubCommand(this, method, anno.value())); }); - commandSet.sort(Comparator.comparingInt(o -> -o.subCommand.length)); + this.commandSet.sort((o1, o2) -> { + int compare = Integer.compare(-o1.subCommand.length, -o2.subCommand.length); + if (compare != 0) { + return compare; + } else { + int i1 = o1.varArgType != null ? Integer.MAX_VALUE : o1.arguments.length; + int i2 = o2.varArgType != null ? Integer.MAX_VALUE : o2.arguments.length; + return Integer.compare(i1, i2); + } + }); commandHelpSet.sort(Comparator.comparingInt(o -> -o.subCommand.length)); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 464517d..7fe7f41 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -110,26 +110,33 @@ public class SWCommandUtils { index++; } - for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - arguments[i + 1] = parameters[i].map(args[index]); - index++; - if (arguments[i + 1] == null) { - throw new CommandParseException(); - } - } - - if (varArgType != null) { - int length = args.length - parameters.length + 1; - Object varArgument = Array.newInstance(varArgType, length); + if (varArgType != null && index > args.length - 1) { + Object varArgument = Array.newInstance(varArgType, 0); arguments[arguments.length - 1] = varArgument; - - for (int i = 0; i < length; i++) { - Object value = parameters[parameters.length - 1].map(args[index]); - if (value == null) { + } else { + for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { + System.out.println(index); + arguments[i + 1] = parameters[i].map(args[index]); + System.out.println(arguments[i + 1]); + index++; + if (arguments[i + 1] == null) { throw new CommandParseException(); } - Array.set(varArgument, i, value); - index++; + } + + if (varArgType != null) { + int length = args.length - parameters.length - subCommand.length + 1; + Object varArgument = Array.newInstance(varArgType, length); + arguments[arguments.length - 1] = varArgument; + + for (int i = 0; i < length; i++) { + Object value = parameters[parameters.length - 1].map(args[index]); + if (value == null) { + throw new CommandParseException(); + } + Array.set(varArgument, i, value); + index++; + } } } return arguments; diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index ad359a3..e4229b6 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -32,9 +32,9 @@ class SubCommand { private SWCommand swCommand; private Method method; String[] subCommand; - private TypeMapper[] arguments; + TypeMapper[] arguments; private Function commandSenderFunction; - private Class varArgType = null; + Class varArgType = null; public SubCommand(SWCommand swCommand, Method method, String[] subCommand) { this(swCommand, method, subCommand, new HashMap<>()); @@ -81,10 +81,10 @@ class SubCommand { } boolean invoke(CommandSender commandSender, String[] args) { - if (args.length < arguments.length - 1) { + if (args.length < arguments.length + subCommand.length - (varArgType != null ? 1 : 0)) { return false; } - if (varArgType == null && args.length > arguments.length) { + if (varArgType == null && args.length > arguments.length + subCommand.length) { return false; } try { @@ -101,7 +101,7 @@ class SubCommand { } List tabComplete(CommandSender commandSender, String[] args) { - if (varArgType == null && args.length < arguments.length - 1) { + if (varArgType == null && args.length < arguments.length + subCommand.length - 1) { return null; } List argsList = new LinkedList<>(Arrays.asList(args)); From 314120a01f59e6523dc6fbad49b6239b8c45f9e8 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 16:14:28 +0200 Subject: [PATCH 66/71] Add ignoreCase subCommands Add ignoreCase tabComplete filter --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 2 +- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 4 +--- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index cbfe7a1..7260a41 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -70,7 +70,7 @@ public abstract class SWCommand { } strings = new ArrayList<>(strings); for (int i = strings.size() - 1; i >= 0; i--) { - if (!strings.get(i).startsWith(args[args.length - 1])) { + if (!strings.get(i).toLowerCase().startsWith(args[args.length - 1].toLowerCase())) { strings.remove(i); } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 7fe7f41..f44b891 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -104,7 +104,7 @@ public class SWCommandUtils { Object[] arguments = new Object[parameters.length + 1]; int index = 0; while (index < subCommand.length) { - if (!args[index].equals(subCommand[index])) { + if (!args[index].equalsIgnoreCase(subCommand[index])) { throw new CommandParseException(); } index++; @@ -115,9 +115,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; } else { for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - System.out.println(index); arguments[i + 1] = parameters[i].map(args[index]); - System.out.println(arguments[i + 1]); index++; if (arguments[i + 1] == null) { throw new CommandParseException(); diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index e4229b6..4742ff2 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -108,7 +108,7 @@ class SubCommand { for (String value : subCommand) { String s = argsList.remove(0); if (argsList.isEmpty()) return Collections.singletonList(value); - if (!value.equals(s)) return null; + if (!value.equalsIgnoreCase(s)) return null; } for (TypeMapper argument : arguments) { String s = argsList.remove(0); From c1e7fdbb1dee40357acc0fad768ce55152f4ddff Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 16:27:20 +0200 Subject: [PATCH 67/71] Add SWCommand.ClassMapper.local --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 7260a41..0c2f743 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -88,7 +88,11 @@ public abstract class SWCommand { } }); addMapper(ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { - SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); + if (anno.local()) { + localTypeMapper.put(anno.value().getTypeName(), typeMapper); + } else { + SWCommandUtils.addMapper(anno.value().getTypeName(), typeMapper); + } }); add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> { if (!anno.help()) { @@ -215,5 +219,7 @@ public abstract class SWCommand { @Target({ElementType.METHOD}) protected @interface ClassMapper { Class value(); + + boolean local() default false; } } From 56c3e730a9941f54fbff77476e842b53bac40021 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 16:54:41 +0200 Subject: [PATCH 68/71] Fix SWCommand localArguments --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 0c2f743..ed29dde 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -136,7 +136,7 @@ public abstract class SWCommand { return; } } - commandSet.add(new SubCommand(this, method, anno.value())); + commandSet.add(new SubCommand(this, method, anno.value(), localTypeMapper)); }); this.commandSet.sort((o1, o2) -> { From 25d72ab3764d7be7b65c9b8c9e763cc92f152ed0 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 17:26:43 +0200 Subject: [PATCH 69/71] Add more TypeMapper capabilities --- SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java | 4 ++-- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 6 +++--- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 4 ++-- SpigotCore_Main/src/de/steamwar/command/TypeMapper.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java index 50901f1..8444aba 100644 --- a/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java +++ b/SpigotCore_Main/src/de/steamwar/acommand/TestCommand.java @@ -37,7 +37,7 @@ public class TestCommand extends SWCommand { } // One Help Command, the first Parameter should be some kind of CommandSender - // The second argument can only be a varAgrs string of what arguments were tried to map + // The second argument can only be a varArgs string of what arguments were tried to map @Register(help = true) public void testHelp(Player player, String... args) { player.sendMessage("This is your help message"); @@ -68,7 +68,7 @@ public class TestCommand extends SWCommand { .collect(Collectors.toList()); return new TypeMapper() { @Override - public Material map(String s) { + public Material map(String[] previous, String s) { return Material.valueOf(s.toUpperCase()); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index f44b891..a4c678d 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -115,7 +115,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; } else { for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - arguments[i + 1] = parameters[i].map(args[index]); + arguments[i + 1] = parameters[i].map(Arrays.copyOf(args, Math.min(index - 1, 0)), args[index]); index++; if (arguments[i + 1] == null) { throw new CommandParseException(); @@ -128,7 +128,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; for (int i = 0; i < length; i++) { - Object value = parameters[parameters.length - 1].map(args[index]); + Object value = parameters[parameters.length - 1].map(Arrays.copyOf(args, Math.min(index - 1, 0)), args[index]); if (value == null) { throw new CommandParseException(); } @@ -156,7 +156,7 @@ public class SWCommandUtils { public static TypeMapper createMapper(Function mapper, BiFunction> tabCompleter) { return new TypeMapper() { @Override - public T map(String s) { + public T map(String[] previous, String s) { return mapper.apply(s); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 4742ff2..1ce4c11 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -114,7 +114,7 @@ class SubCommand { String s = argsList.remove(0); if (argsList.isEmpty()) return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { - if (argument.map(s) == null) { + if (argument.map(Arrays.copyOf(args, argsList.size()), s) == null) { return null; } } catch (Exception e) { @@ -126,7 +126,7 @@ class SubCommand { String s = argsList.remove(0); if (argsList.isEmpty()) return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); try { - if (arguments[arguments.length - 1].map(s) == null) { + if (arguments[arguments.length - 1].map(Arrays.copyOf(args, argsList.size()), s) == null) { return null; } } catch (Exception e) { diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java index 90dbf1e..27b04f7 100644 --- a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java +++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java @@ -24,7 +24,7 @@ import org.bukkit.command.CommandSender; import java.util.List; public interface TypeMapper { - T map(String s); + T map(String[] previousArguments, String s); List tabCompletes(CommandSender commandSender, String[] previousArguments, String s); } From fa9268ce1b1599743efc42ef65f8eb3fdcf1d465 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 17:56:17 +0200 Subject: [PATCH 70/71] Fix NegativeArraySizeException in SWCommandUtils --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 1 - SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index ed29dde..240766b 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -103,7 +103,6 @@ public abstract class SWCommand { } if (!parameters[parameters.length - 1].isVarArgs()) { Bukkit.getLogger().log(Level.WARNING, "The method '" + method.toString() + "' is lacking the varArgs parameters as last Argument"); - return; } 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"); diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index a4c678d..dc34536 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -115,7 +115,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; } else { for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - arguments[i + 1] = parameters[i].map(Arrays.copyOf(args, Math.min(index - 1, 0)), args[index]); + arguments[i + 1] = parameters[i].map(Arrays.copyOf(args, Math.max(index - 1, 0)), args[index]); index++; if (arguments[i + 1] == null) { throw new CommandParseException(); @@ -128,7 +128,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; for (int i = 0; i < length; i++) { - Object value = parameters[parameters.length - 1].map(Arrays.copyOf(args, Math.min(index - 1, 0)), args[index]); + Object value = parameters[parameters.length - 1].map(Arrays.copyOf(args, Math.max(index - 1, 0)), args[index]); if (value == null) { throw new CommandParseException(); } From 2edb3dd9511fa7d05cc0c81d188678878673d617 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 30 Mar 2021 18:05:29 +0200 Subject: [PATCH 71/71] Fix stuff --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index dc34536..1536d51 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -115,7 +115,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; } else { for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - arguments[i + 1] = parameters[i].map(Arrays.copyOf(args, Math.max(index - 1, 0)), args[index]); + arguments[i + 1] = parameters[i].map(Arrays.copyOf(args, index), args[index]); index++; if (arguments[i + 1] == null) { throw new CommandParseException(); @@ -128,7 +128,7 @@ public class SWCommandUtils { arguments[arguments.length - 1] = varArgument; for (int i = 0; i < length; i++) { - Object value = parameters[parameters.length - 1].map(Arrays.copyOf(args, Math.max(index - 1, 0)), args[index]); + Object value = parameters[parameters.length - 1].map(Arrays.copyOf(args, index), args[index]); if (value == null) { throw new CommandParseException(); }