From 373612f24baa58f354d80657d988974e4f410c90 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 15 Nov 2021 19:38:33 +0100 Subject: [PATCH 1/5] Add GuardChecker --- .../src/de/steamwar/command/GuardChecker.java | 30 ++++++++++++++ .../src/de/steamwar/command/SWCommand.java | 39 +++++++++++++++++- .../de/steamwar/command/SWCommandUtils.java | 13 +++++- .../src/de/steamwar/command/SubCommand.java | 41 ++++++++++++++++++- 4 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/command/GuardChecker.java diff --git a/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java b/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java new file mode 100644 index 0000000..ac3fa3c --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java @@ -0,0 +1,30 @@ +/* + * 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; + +@FunctionalInterface +public interface GuardChecker { + /** + * While guarding the first parameter of the command the parameter s of this method is {@code null} + */ + boolean guard(CommandSender commandSender, String[] previousArguments, String s); +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 1db2988..f649a1a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -39,6 +39,7 @@ public abstract class SWCommand { private final List commandList = new ArrayList<>(); private final List commandHelpList = new ArrayList<>(); private final Map> localTypeMapper = new HashMap<>(); + private final Map localGuardChecker = new HashMap<>(); protected SWCommand(String command) { this(command, new String[0]); @@ -85,6 +86,13 @@ public abstract class SWCommand { addMapper(ClassMapper.class, method, i -> i == 0, false, TypeMapper.class, (anno, typeMapper) -> { (anno.local() ? localTypeMapper : SWCommandUtils.MAPPER_FUNCTIONS).putIfAbsent(anno.value().getTypeName(), typeMapper); }); + addGuard(Guard.class, method, i -> i == 0, false, GuardChecker.class, (anno, guardChecker) -> { + (anno.local() ? localGuardChecker : SWCommandUtils.GUARD_FUNCTIONS).putIfAbsent(anno.value(), guardChecker); + }); + addGuard(ClassGuard.class, method, i -> i == 0, false, GuardChecker.class, (anno, guardChecker) -> { + (anno.local() ? localGuardChecker : SWCommandUtils.GUARD_FUNCTIONS).putIfAbsent(anno.value().getTypeName(), guardChecker); + }); + add(Register.class, method, i -> i > 0, true, null, (anno, parameters) -> { if (!anno.help()) return; if (parameters.length != 2) { @@ -97,7 +105,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; } - commandHelpList.add(new SubCommand(this, method, anno.value(), new HashMap<>())); + commandHelpList.add(new SubCommand(this, method, anno.value(), new HashMap<>(), localGuardChecker)); }); } for (Method method : methods) { @@ -119,7 +127,7 @@ public abstract class SWCommand { return; } } - commandList.add(new SubCommand(this, method, anno.value(), localTypeMapper)); + commandList.add(new SubCommand(this, method, anno.value(), localTypeMapper, localGuardChecker)); }); this.commandList.sort((o1, o2) -> { @@ -167,6 +175,17 @@ public abstract class SWCommand { }); } + private void addGuard(Class annotation, Method method, IntPredicate parameterTester, boolean firstParameter, Class returnType, BiConsumer consumer) { + add(annotation, method, parameterTester, firstParameter, returnType, (anno, parameters) -> { + try { + method.setAccessible(true); + consumer.accept(anno, (GuardChecker) method.invoke(this)); + } catch (Exception e) { + throw new SecurityException(e.getMessage(), e); + } + }); + } + public void unregister() { SWCommandUtils.knownCommandMap.remove(command.getName()); command.getAliases().forEach(SWCommandUtils.knownCommandMap::remove); @@ -207,4 +226,20 @@ public abstract class SWCommand { boolean local() default false; } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.PARAMETER, ElementType.METHOD}) + protected @interface Guard { + String value() default ""; + + boolean local() default false; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.METHOD}) + protected @interface ClassGuard { + Class 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 64c735d..39e56d5 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -44,6 +44,7 @@ public class SWCommandUtils { } static final Map> MAPPER_FUNCTIONS = new HashMap<>(); + static final Map GUARD_FUNCTIONS = new HashMap<>(); static final TypeMapper ERROR_FUNCTION = createMapper(s -> { throw new SecurityException(); @@ -100,7 +101,7 @@ public class SWCommandUtils { } } - static Object[] generateArgumentArray(CommandSender commandSender, TypeMapper[] parameters, String[] args, Class varArgType, String[] subCommand) throws CommandParseException { + static Object[] generateArgumentArray(CommandSender commandSender, TypeMapper[] parameters, GuardChecker[] guards, String[] args, Class varArgType, String[] subCommand) throws CommandParseException { Object[] arguments = new Object[parameters.length + 1]; int index = 0; while (index < subCommand.length) { @@ -116,6 +117,7 @@ public class SWCommandUtils { } for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { + if (guards[i] != null && !guards[i].guard(commandSender, Arrays.copyOf(args, index), args[index])) throw new CommandParseException(); arguments[i + 1] = parameters[i].map(commandSender, Arrays.copyOf(args, index), args[index]); index++; if (arguments[i + 1] == null) throw new CommandParseException(); @@ -125,6 +127,7 @@ public class SWCommandUtils { Object varArgument = arguments[arguments.length - 1]; for (int i = 0; i < length; i++) { + if (guards[guards.length - 1] != null && !guards[guards.length - 1].guard(commandSender, Arrays.copyOf(args, index), args[index])) throw new CommandParseException(); Object value = parameters[parameters.length - 1].map(commandSender, Arrays.copyOf(args, index), args[index]); if (value == null) throw new CommandParseException(); Array.set(varArgument, i, value); @@ -142,6 +145,14 @@ public class SWCommandUtils { MAPPER_FUNCTIONS.putIfAbsent(name, mapper); } + public static void addGuard(Class clazz, GuardChecker guardChecker) { + addGuard(clazz.getTypeName(), guardChecker); + } + + public static void addGuard(String name, GuardChecker guardChecker) { + GUARD_FUNCTIONS.putIfAbsent(name, guardChecker); + } + public static TypeMapper createMapper(Function mapper, Function> tabCompleter) { return createMapper(mapper, (commandSender, s) -> tabCompleter.apply(s)); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 15dad9a..e32dc38 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; @@ -27,6 +28,7 @@ import java.lang.reflect.Parameter; import java.util.*; import java.util.function.Function; import java.util.function.Predicate; +import java.util.logging.Level; import static de.steamwar.command.SWCommandUtils.*; @@ -36,11 +38,13 @@ class SubCommand { private Method method; String[] subCommand; TypeMapper[] arguments; + GuardChecker[] guards; private Predicate commandSenderPredicate; private Function commandSenderFunction; + private GuardChecker guardChecker; Class varArgType = null; - SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper) { + SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker) { this.swCommand = swCommand; this.method = method; @@ -48,8 +52,10 @@ class SubCommand { commandSenderPredicate = sender -> parameters[0].getType().isAssignableFrom(sender.getClass()); commandSenderFunction = sender -> parameters[0].getType().cast(sender); this.subCommand = subCommand; + guardChecker = getGuardChecker(parameters[0], localGuardChecker); arguments = new TypeMapper[parameters.length - 1]; + guards = new GuardChecker[parameters.length - 1]; for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; Class clazz = parameter.getType(); @@ -76,9 +82,22 @@ class SubCommand { arguments[i - 1] = localTypeMapper.containsKey(name) ? localTypeMapper.get(name) : MAPPER_FUNCTIONS.getOrDefault(name, ERROR_FUNCTION); + guards[i - 1] = getGuardChecker(parameter, localGuardChecker); } } + private GuardChecker getGuardChecker(Parameter parameter, Map localGuardChecker) { + SWCommand.Guard guard = parameter.getAnnotation(SWCommand.Guard.class); + if (guard != null) { + GuardChecker current = localGuardChecker.getOrDefault(guard.value(), GUARD_FUNCTIONS.getOrDefault(guard.value(), null)); + if (guardChecker == null) { + Bukkit.getLogger().log(Level.WARNING, () -> "The guard checker with name '" + guard.value() + "' is neither a local guard checker nor a global one"); + } + return current; + } + return null; + } + boolean invoke(CommandSender commandSender, String[] args) { if (args.length < arguments.length + subCommand.length - (varArgType != null ? 1 : 0)) { return false; @@ -90,7 +109,10 @@ class SubCommand { if (!commandSenderPredicate.test(commandSender)) { return false; } - Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, arguments, args, varArgType, subCommand); + if (!guardChecker.guard(commandSender, new String[0], null)) { + return false; + } + Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, arguments, guards, args, varArgType, subCommand); objects[0] = commandSenderFunction.apply(commandSender); method.setAccessible(true); method.invoke(swCommand, objects); @@ -106,6 +128,9 @@ class SubCommand { if (varArgType == null && args.length > arguments.length + subCommand.length) { return null; } + if (guardChecker != null && !guardChecker.guard(commandSender, new String[0], null)) { + return null; + } int index = 0; List argsList = new LinkedList<>(Arrays.asList(args)); for (String value : subCommand) { @@ -117,9 +142,15 @@ class SubCommand { for (TypeMapper argument : arguments) { String s = argsList.remove(0); if (argsList.isEmpty()) { + if (guards[index] != null && !guards[index].guard(commandSender, Arrays.copyOf(args, args.length - 1), s)) { + return null; + } return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); } try { + if (guards[index] != null && !guards[index].guard(commandSender, Arrays.copyOf(args, index), s)) { + return null; + } if (argument.map(commandSender, Arrays.copyOf(args, index), s) == null) { return null; } @@ -132,9 +163,15 @@ class SubCommand { while (!argsList.isEmpty()) { String s = argsList.remove(0); if (argsList.isEmpty()) { + if (guards[guards.length - 1] != null && !guards[guards.length - 1].guard(commandSender, Arrays.copyOf(args, args.length - 1), s)) { + return null; + } return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); } try { + if (guards[guards.length - 1] != null && !guards[guards.length - 1].guard(commandSender, Arrays.copyOf(args, index), s)) { + return null; + } if (arguments[arguments.length - 1].map(commandSender, Arrays.copyOf(args, index), s) == null) { return null; } -- 2.39.2 From b1f7f205ad1c8ad3c394e25ae3df2fb9306d17a5 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Mon, 15 Nov 2021 23:55:37 +0100 Subject: [PATCH 2/5] Add SubCommand --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index e32dc38..9496d8c 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -89,6 +89,9 @@ class SubCommand { private GuardChecker getGuardChecker(Parameter parameter, Map localGuardChecker) { SWCommand.Guard guard = parameter.getAnnotation(SWCommand.Guard.class); if (guard != null) { + if (guard.value() == null || guard.value().isEmpty()) { + return GUARD_FUNCTIONS.getOrDefault(parameter.getType().getTypeName(), null); + } GuardChecker current = localGuardChecker.getOrDefault(guard.value(), GUARD_FUNCTIONS.getOrDefault(guard.value(), null)); if (guardChecker == null) { Bukkit.getLogger().log(Level.WARNING, () -> "The guard checker with name '" + guard.value() + "' is neither a local guard checker nor a global one"); -- 2.39.2 From d9bb62d5f3e3173007dface942c425d16fbaeb6c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Nov 2021 20:41:49 +0100 Subject: [PATCH 3/5] Add CommandNoHelpException Add GuardCheckType Add GuardResult --- .../command/CommandNoHelpException.java | 26 ++++++++++++++++ .../de/steamwar/command/GuardCheckType.java | 25 ++++++++++++++++ .../src/de/steamwar/command/GuardChecker.java | 2 +- .../src/de/steamwar/command/GuardResult.java | 26 ++++++++++++++++ .../src/de/steamwar/command/SWCommand.java | 8 +++-- .../de/steamwar/command/SWCommandUtils.java | 2 -- .../src/de/steamwar/command/SubCommand.java | 30 ++++++++++++++----- 7 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/command/CommandNoHelpException.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/GuardResult.java diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandNoHelpException.java b/SpigotCore_Main/src/de/steamwar/command/CommandNoHelpException.java new file mode 100644 index 0000000..41b487b --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/CommandNoHelpException.java @@ -0,0 +1,26 @@ +/* + * 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; + +class CommandNoHelpException extends RuntimeException { + + CommandNoHelpException() { + } +} diff --git a/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java b/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java new file mode 100644 index 0000000..f2b2214 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java @@ -0,0 +1,25 @@ +/* + * 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 enum GuardCheckType { + COMMAND, + TAB_COMPLETE +} diff --git a/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java b/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java index ac3fa3c..e8f3a1f 100644 --- a/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java +++ b/SpigotCore_Main/src/de/steamwar/command/GuardChecker.java @@ -26,5 +26,5 @@ public interface GuardChecker { /** * While guarding the first parameter of the command the parameter s of this method is {@code null} */ - boolean guard(CommandSender commandSender, String[] previousArguments, String s); + GuardResult guard(CommandSender commandSender, GuardCheckType guardCheckType, String[] previousArguments, String s); } diff --git a/SpigotCore_Main/src/de/steamwar/command/GuardResult.java b/SpigotCore_Main/src/de/steamwar/command/GuardResult.java new file mode 100644 index 0000000..9ffbf77 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/GuardResult.java @@ -0,0 +1,26 @@ +/* + * 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 enum GuardResult { + ALLOWED, + DENIED_WITH_HELP, + DENIED +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index f649a1a..fe6387e 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -52,8 +52,12 @@ public abstract class SWCommand { if (!initialized) { createMapping(); } - if (!commandList.stream().anyMatch(s -> s.invoke(sender, args))) { - commandHelpList.stream().anyMatch(s -> s.invoke(sender, args)); + try { + if (!commandList.stream().anyMatch(s -> s.invoke(sender, args))) { + commandHelpList.stream().anyMatch(s -> s.invoke(sender, args)); + } + } catch (CommandNoHelpException e) { + // Ignored } return false; } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 39e56d5..52e362e 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -117,7 +117,6 @@ public class SWCommandUtils { } for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - if (guards[i] != null && !guards[i].guard(commandSender, Arrays.copyOf(args, index), args[index])) throw new CommandParseException(); arguments[i + 1] = parameters[i].map(commandSender, Arrays.copyOf(args, index), args[index]); index++; if (arguments[i + 1] == null) throw new CommandParseException(); @@ -127,7 +126,6 @@ public class SWCommandUtils { Object varArgument = arguments[arguments.length - 1]; for (int i = 0; i < length; i++) { - if (guards[guards.length - 1] != null && !guards[guards.length - 1].guard(commandSender, Arrays.copyOf(args, index), args[index])) throw new CommandParseException(); Object value = parameters[parameters.length - 1].map(commandSender, Arrays.copyOf(args, index), args[index]); if (value == null) throw new CommandParseException(); Array.set(varArgument, i, value); diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 9496d8c..426abc6 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -112,11 +112,25 @@ class SubCommand { if (!commandSenderPredicate.test(commandSender)) { return false; } - if (!guardChecker.guard(commandSender, new String[0], null)) { - return false; - } Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, arguments, guards, args, varArgType, subCommand); objects[0] = commandSenderFunction.apply(commandSender); + for (int i = 0; i < objects.length; i++) { + GuardChecker current; + if (i == 0 && guardChecker != null) { + current = guardChecker; + } else { + current = guards[i - 1]; + } + if (current != null) { + GuardResult guardResult = current.guard(commandSender, GuardCheckType.COMMAND, new String[0], null); + if (guardResult != GuardResult.ALLOWED) { + if (guardResult == GuardResult.DENIED) { + throw new CommandNoHelpException(); + } + return false; + } + } + } method.setAccessible(true); method.invoke(swCommand, objects); } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) { @@ -131,7 +145,7 @@ class SubCommand { if (varArgType == null && args.length > arguments.length + subCommand.length) { return null; } - if (guardChecker != null && !guardChecker.guard(commandSender, new String[0], null)) { + if (guardChecker != null && guardChecker.guard(commandSender, GuardCheckType.TAB_COMPLETE, new String[0], null) != GuardResult.ALLOWED) { return null; } int index = 0; @@ -145,13 +159,13 @@ class SubCommand { for (TypeMapper argument : arguments) { String s = argsList.remove(0); if (argsList.isEmpty()) { - if (guards[index] != null && !guards[index].guard(commandSender, Arrays.copyOf(args, args.length - 1), s)) { + if (guards[index] != null && guards[index].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, args.length - 1), s) != GuardResult.ALLOWED) { return null; } return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); } try { - if (guards[index] != null && !guards[index].guard(commandSender, Arrays.copyOf(args, index), s)) { + if (guards[index] != null && guards[index].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, index), s) != GuardResult.ALLOWED) { return null; } if (argument.map(commandSender, Arrays.copyOf(args, index), s) == null) { @@ -166,13 +180,13 @@ class SubCommand { while (!argsList.isEmpty()) { String s = argsList.remove(0); if (argsList.isEmpty()) { - if (guards[guards.length - 1] != null && !guards[guards.length - 1].guard(commandSender, Arrays.copyOf(args, args.length - 1), s)) { + if (guards[guards.length - 1] != null && guards[guards.length - 1].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, args.length - 1), s) != GuardResult.ALLOWED) { return null; } return arguments[arguments.length - 1].tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); } try { - if (guards[guards.length - 1] != null && !guards[guards.length - 1].guard(commandSender, Arrays.copyOf(args, index), s)) { + if (guards[guards.length - 1] != null && guards[guards.length - 1].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, index), s) != GuardResult.ALLOWED) { return null; } if (arguments[arguments.length - 1].map(commandSender, Arrays.copyOf(args, index), s) == null) { -- 2.39.2 From cc5d43519997e9516da80850be773c917e3c4c90 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Nov 2021 21:18:42 +0100 Subject: [PATCH 4/5] Add GuardCheckType.HELP_COMMAND --- .../src/de/steamwar/command/GuardCheckType.java | 1 + .../src/de/steamwar/command/SWCommand.java | 4 ++-- .../src/de/steamwar/command/SubCommand.java | 16 +++++++++++----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java b/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java index f2b2214..0f023b8 100644 --- a/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java +++ b/SpigotCore_Main/src/de/steamwar/command/GuardCheckType.java @@ -21,5 +21,6 @@ package de.steamwar.command; public enum GuardCheckType { COMMAND, + HELP_COMMAND, TAB_COMPLETE } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index fe6387e..99864c2 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -109,7 +109,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; } - commandHelpList.add(new SubCommand(this, method, anno.value(), new HashMap<>(), localGuardChecker)); + commandHelpList.add(new SubCommand(this, method, anno.value(), new HashMap<>(), localGuardChecker, true)); }); } for (Method method : methods) { @@ -131,7 +131,7 @@ public abstract class SWCommand { return; } } - commandList.add(new SubCommand(this, method, anno.value(), localTypeMapper, localGuardChecker)); + commandList.add(new SubCommand(this, method, anno.value(), localTypeMapper, localGuardChecker, false)); }); this.commandList.sort((o1, o2) -> { diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 426abc6..87b9485 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -43,10 +43,12 @@ class SubCommand { private Function commandSenderFunction; private GuardChecker guardChecker; Class varArgType = null; + private boolean help = false; - SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker) { + SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker, boolean help) { this.swCommand = swCommand; this.method = method; + this.help = help; Parameter[] parameters = method.getParameters(); commandSenderPredicate = sender -> parameters[0].getType().isAssignableFrom(sender.getClass()); @@ -116,13 +118,13 @@ class SubCommand { objects[0] = commandSenderFunction.apply(commandSender); for (int i = 0; i < objects.length; i++) { GuardChecker current; - if (i == 0 && guardChecker != null) { + if (i == 0) { current = guardChecker; } else { current = guards[i - 1]; } if (current != null) { - GuardResult guardResult = current.guard(commandSender, GuardCheckType.COMMAND, new String[0], null); + GuardResult guardResult = current.guard(commandSender, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, new String[0], null); if (guardResult != GuardResult.ALLOWED) { if (guardResult == GuardResult.DENIED) { throw new CommandNoHelpException(); @@ -133,6 +135,8 @@ class SubCommand { } method.setAccessible(true); method.invoke(swCommand, objects); + } catch (CommandNoHelpException e) { + throw e; } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) { throw new SecurityException(e.getMessage(), e); } catch (CommandParseException e) { @@ -156,16 +160,17 @@ class SubCommand { if (!value.equalsIgnoreCase(s)) return null; index++; } + int guardIndex = 0; for (TypeMapper argument : arguments) { String s = argsList.remove(0); if (argsList.isEmpty()) { - if (guards[index] != null && guards[index].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, args.length - 1), s) != GuardResult.ALLOWED) { + if (guards[guardIndex] != null && guards[guardIndex].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, args.length - 1), s) != GuardResult.ALLOWED) { return null; } return argument.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), s); } try { - if (guards[index] != null && guards[index].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, index), s) != GuardResult.ALLOWED) { + if (guards[guardIndex] != null && guards[guardIndex].guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, index), s) != GuardResult.ALLOWED) { return null; } if (argument.map(commandSender, Arrays.copyOf(args, index), s) == null) { @@ -175,6 +180,7 @@ class SubCommand { return null; } index++; + guardIndex++; } if (varArgType != null && !argsList.isEmpty()) { while (!argsList.isEmpty()) { -- 2.39.2 From b1808eb4c5c538da794e503529a17da106bed2a9 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 16 Nov 2021 21:20:32 +0100 Subject: [PATCH 5/5] Add GuardCheckType.HELP_COMMAND --- 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 87b9485..c1cb92a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -43,7 +43,7 @@ class SubCommand { private Function commandSenderFunction; private GuardChecker guardChecker; Class varArgType = null; - private boolean help = false; + private boolean help; SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker, boolean help) { this.swCommand = swCommand; -- 2.39.2