From 13b6dcd74b865e174a131f630301781fd3da88d3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 8 Dec 2021 22:39:56 +0100 Subject: [PATCH 01/27] Add testing to SpigotCore_Main Add CommandRegistering Add initial implementation for CommandPart --- SpigotCore_Main/build.gradle | 16 +++ .../command/CommandParseException.java | 2 +- .../src/de/steamwar/command/CommandPart.java | 119 +++++++++++++++++ .../steamwar/command/CommandRegistering.java | 63 +++++++++ .../src/de/steamwar/command/SWCommand.java | 71 +++++++--- .../de/steamwar/command/SWCommandUtils.java | 22 ---- .../src/de/steamwar/command/SubCommand.java | 4 +- .../src/de/steamwar/core/Core.java | 1 - SpigotCore_Main/testsrc/.gitkeep | 0 .../de/steamwar/TestCommandSender.java | 122 ++++++++++++++++++ .../steamwar/command/ExecutionIdentifier.java | 41 ++++++ .../de/steamwar/command/SimpleCommand.java | 34 +++++ .../steamwar/command/SimpleCommandTest.java | 60 +++++++++ 13 files changed, 508 insertions(+), 47 deletions(-) create mode 100644 SpigotCore_Main/src/de/steamwar/command/CommandPart.java create mode 100644 SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java create mode 100644 SpigotCore_Main/testsrc/.gitkeep create mode 100644 SpigotCore_Main/testsrc/de/steamwar/TestCommandSender.java create mode 100644 SpigotCore_Main/testsrc/de/steamwar/command/ExecutionIdentifier.java create mode 100644 SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommand.java create mode 100644 SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java diff --git a/SpigotCore_Main/build.gradle b/SpigotCore_Main/build.gradle index 746d01e..8e751bf 100644 --- a/SpigotCore_Main/build.gradle +++ b/SpigotCore_Main/build.gradle @@ -40,6 +40,16 @@ sourceSets { exclude '**/*.java', '**/*.kt' } } + + test { + java { + srcDirs = ['testsrc'] + } + resources { + srcDirs = ['testsrc'] + exclude '**/*.java', '**/*.kt' + } + } } dependencies { @@ -51,6 +61,12 @@ dependencies { testCompileOnly 'org.projectlombok:lombok:1.18.22' annotationProcessor 'org.projectlombok:lombok:1.18.22' testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' + + testImplementation files("${project.rootDir}/lib/Spigot-1.15.jar") + testImplementation files("${project.rootDir}/lib/WorldEdit-1.12.jar") + + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.hamcrest:hamcrest:2.2' } processResources { diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java b/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java index 21e68bb..3d81ea6 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandParseException.java @@ -19,7 +19,7 @@ package de.steamwar.command; -public class CommandParseException extends Exception { +public class CommandParseException extends RuntimeException { public CommandParseException() { } diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java new file mode 100644 index 0000000..bcb6c3f --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -0,0 +1,119 @@ +/* + * 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 lombok.AllArgsConstructor; +import org.bukkit.command.CommandSender; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.List; + +public class CommandPart { + private static final String[] EMPTY_ARRAY = new String[0]; + + @AllArgsConstructor + private static class CheckArgumentResult { + private final boolean success; + private final Object value; + } + + private TypeMapper typeMapper; + private GuardChecker guard; + private Class varArgType = null; + private String optional = null; + private boolean help; + + private CommandPart next = null; + + CommandPart(TypeMapper typeMapper, GuardChecker guard, Class varArgType, String optional, boolean help) { + this.typeMapper = typeMapper; + this.guard = guard; + if (optional != null && varArgType != null) { + throw new IllegalArgumentException("A vararg part can't have an optional part!"); + } + this.varArgType = varArgType; + this.optional = optional; + this.help = help; + } + + void setNext(CommandPart next) { + if (varArgType != null) { + throw new IllegalArgumentException("There can't be a next part if this is a vararg part!"); + } + this.next = next; + } + + void generateArgumentArray(List current, CommandSender commandSender, String[] args, int startIndex) { + if (startIndex >= args.length) { + return; + } + + if (varArgType != null) { + Object array = Array.newInstance(varArgType, args.length - startIndex); + for (int i = startIndex; i < args.length; i++) { + CheckArgumentResult validArgument = checkArgument(help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, commandSender, args, i); + if (!validArgument.success) { + throw new CommandParseException(); + } + Array.set(array, i - startIndex, validArgument.value); + } + current.add(array); + return; + } + + CheckArgumentResult validArgument = checkArgument(help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, commandSender, args, startIndex); + if (!validArgument.success && optional == null) { + throw new CommandParseException(); + } + if (optional != null) { + current.add(typeMapper.map(commandSender, EMPTY_ARRAY, optional)); + next.generateArgumentArray(current, commandSender, args, startIndex); + return; + } + current.add(validArgument.value); + next.generateArgumentArray(current, commandSender, args, startIndex + 1); + } + + void generateTabComplete(List current, CommandSender commandSender, String[] args, int startIndex) { + + } + + private CheckArgumentResult checkArgument(GuardCheckType guardCheckType, CommandSender commandSender, String[] args, int index) { + try { + Object value = typeMapper.map(commandSender, Arrays.copyOf(args, index - 1), args[index]); + if (guard != null) { + GuardResult guardResult = guard.guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, index - 1), args[index]); + switch (guardResult) { + case ALLOWED: + return new CheckArgumentResult(true, value); + case DENIED: + throw new CommandNoHelpException(); + case DENIED_WITH_HELP: + default: + return new CheckArgumentResult(false, null); + } + } + return new CheckArgumentResult(true, value); + } catch (Exception e) { + return new CheckArgumentResult(false, null); + } + } +} diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java b/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java new file mode 100644 index 0000000..8cbf59f --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java @@ -0,0 +1,63 @@ +/* + * 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.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; + +import java.lang.reflect.Field; +import java.util.Map; + +class CommandRegistering { + + private static final CommandMap commandMap; + private static final Map knownCommandMap; + + 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 registered.", exception); + } + try { + final Field knownCommandsField = SimpleCommandMap.class.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 void unregister(Command command) { + knownCommandMap.remove(command.getName()); + command.getAliases().forEach(knownCommandMap::remove); + command.unregister(commandMap); + } + + static void register(Command command) { + commandMap.register("steamwar", command); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 1783303..7126fe8 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -61,13 +61,7 @@ public abstract class SWCommand { if (!initialized) { createMapping(); } - try { - if (!commandList.stream().anyMatch(s -> s.invoke(sender, args))) { - commandHelpList.stream().anyMatch(s -> s.invoke(sender, args)); - } - } catch (CommandNoHelpException e) { - // Ignored - } + SWCommand.this.execute(sender, alias, args); return false; } @@ -76,21 +70,52 @@ public abstract class SWCommand { if (!initialized) { createMapping(); } - String string = args[args.length - 1].toLowerCase(); - return commandList.stream() - .filter(s -> !s.noTabComplete) - .map(s -> s.tabComplete(sender, args)) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .filter(s -> !s.isEmpty()) - .filter(s -> s.toLowerCase().startsWith(string)) - .collect(Collectors.toList()); + return SWCommand.this.tabComplete(sender, alias, args); } }; unregister(); register(); } + // This is used for the tests! + SWCommand(boolean noRegister, String command, String... aliases) { + this.command = new Command(command, "", "/" + command, Arrays.asList(aliases)) { + @Override + public boolean execute(CommandSender sender, String alias, String[] args) { + SWCommand.this.execute(sender, alias, args); + return false; + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + return SWCommand.this.tabComplete(sender, alias, args); + } + }; + createMapping(); + } + + void execute(CommandSender sender, String alias, String[] args) { + try { + if (!commandList.stream().anyMatch(s -> s.invoke(sender, args))) { + commandHelpList.stream().anyMatch(s -> s.invoke(sender, args)); + } + } catch (CommandNoHelpException e) { + // Ignored + } + } + + List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException { + String string = args[args.length - 1].toLowerCase(); + return commandList.stream() + .filter(s -> !s.noTabComplete) + .map(s -> s.tabComplete(sender, args)) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(s -> !s.isEmpty()) + .filter(s -> s.toLowerCase().startsWith(string)) + .collect(Collectors.toList()); + } + private synchronized void createMapping() { List methods = methods(); for (Method method : methods) { @@ -219,13 +244,11 @@ public abstract class SWCommand { } public void unregister() { - SWCommandUtils.knownCommandMap.remove(command.getName()); - command.getAliases().forEach(SWCommandUtils.knownCommandMap::remove); - command.unregister(SWCommandUtils.commandMap); + CommandRegistering.unregister(command); } public void register() { - SWCommandUtils.commandMap.register("steamwar", this.command); + CommandRegistering.register(command); } @Register(help = true) @@ -332,6 +355,12 @@ public abstract class SWCommand { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) protected @interface StaticValue { - String[] value() default {}; + String[] value(); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.PARAMETER}) + protected @interface OptionalValue { + String defaultValue(); // Will pe parsed against the TypeMapper specified by the parameter or annotation } } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index dbe616a..0ee8562 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -91,28 +91,6 @@ public class SWCommandUtils { MAPPER_FUNCTIONS.put(alternativeClazz.getTypeName(), mapper); } - static final CommandMap commandMap; - static final Map knownCommandMap; - - 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 registered.", exception); - } - try { - final Field knownCommandsField = SimpleCommandMap.class.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(CommandSender commandSender, TypeMapper[] parameters, GuardChecker[] guards, String[] args, Class varArgType, String[] subCommand) throws CommandParseException { Object[] arguments = new Object[parameters.length + 1]; int index = 0; diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 997cdea..07f05d8 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -179,10 +179,10 @@ class SubCommand { method.invoke(swCommand, objects); } catch (CommandNoHelpException e) { throw e; - } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) { - throw new SecurityException(e.getMessage(), e); } catch (CommandParseException e) { return false; + } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) { + throw new SecurityException(e.getMessage(), e); } return true; } diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index 82f0705..b0fc18f 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -38,7 +38,6 @@ import java.util.logging.Level; public class Core extends JavaPlugin{ - private static Core instance; private static final int version; public static Message MESSAGE; diff --git a/SpigotCore_Main/testsrc/.gitkeep b/SpigotCore_Main/testsrc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/SpigotCore_Main/testsrc/de/steamwar/TestCommandSender.java b/SpigotCore_Main/testsrc/de/steamwar/TestCommandSender.java new file mode 100644 index 0000000..02760e4 --- /dev/null +++ b/SpigotCore_Main/testsrc/de/steamwar/TestCommandSender.java @@ -0,0 +1,122 @@ +/* + * 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; + +import org.bukkit.Server; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionAttachment; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.plugin.Plugin; + +import java.util.Set; + +public class TestCommandSender implements CommandSender { + + @Override + public void sendMessage(String s) { + + } + + @Override + public void sendMessage(String[] strings) { + + } + + @Override + public Server getServer() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public Spigot spigot() { + return null; + } + + @Override + public boolean isPermissionSet(String s) { + return false; + } + + @Override + public boolean isPermissionSet(Permission permission) { + return false; + } + + @Override + public boolean hasPermission(String s) { + return false; + } + + @Override + public boolean hasPermission(Permission permission) { + return false; + } + + @Override + public PermissionAttachment addAttachment(Plugin plugin, String s, boolean b) { + return null; + } + + @Override + public PermissionAttachment addAttachment(Plugin plugin) { + return null; + } + + @Override + public PermissionAttachment addAttachment(Plugin plugin, String s, boolean b, int i) { + return null; + } + + @Override + public PermissionAttachment addAttachment(Plugin plugin, int i) { + return null; + } + + @Override + public void removeAttachment(PermissionAttachment permissionAttachment) { + + } + + @Override + public void recalculatePermissions() { + + } + + @Override + public Set getEffectivePermissions() { + return null; + } + + @Override + public boolean isOp() { + return false; + } + + @Override + public void setOp(boolean b) { + + } +} diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/ExecutionIdentifier.java b/SpigotCore_Main/testsrc/de/steamwar/command/ExecutionIdentifier.java new file mode 100644 index 0000000..e4ed591 --- /dev/null +++ b/SpigotCore_Main/testsrc/de/steamwar/command/ExecutionIdentifier.java @@ -0,0 +1,41 @@ +/* + * 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 ExecutionIdentifier extends RuntimeException { + public ExecutionIdentifier() { + } + + public ExecutionIdentifier(String message) { + super(message); + } + + public ExecutionIdentifier(String message, Throwable cause) { + super(message, cause); + } + + public ExecutionIdentifier(Throwable cause) { + super(cause); + } + + public ExecutionIdentifier(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommand.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommand.java new file mode 100644 index 0000000..79f2844 --- /dev/null +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommand.java @@ -0,0 +1,34 @@ +/* + * 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; + +public class SimpleCommand extends SWCommand { + + public SimpleCommand() { + super(true, "simple"); + } + + @Register + public void execute(CommandSender sender) { + throw new ExecutionIdentifier("Simple execute without any parameters"); + } +} diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java new file mode 100644 index 0000000..f8ba72a --- /dev/null +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java @@ -0,0 +1,60 @@ +/* + * 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 de.steamwar.TestCommandSender; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class SimpleCommandTest { + + private SimpleCommand simpleCommand; + + @Before + public void setUp() throws Exception { + simpleCommand = new SimpleCommand(); + } + + @Test + public void testCommandParsing() { + try { + simpleCommand.execute(new TestCommandSender(), "", new String[]{}); + } catch (SecurityException securityException) { + if (securityException.getCause().getCause() instanceof ExecutionIdentifier) { + ExecutionIdentifier executionIdentifier = (ExecutionIdentifier) securityException.getCause().getCause(); + assertThat(executionIdentifier.getMessage(), is("Simple execute without any parameters")); + return; + } + } + assert false; + } + + @Test + public void testUnknownCommandParsing() { + try { + simpleCommand.execute(new TestCommandSender(), "", new String[]{"unknown"}); + } catch (SecurityException securityException) { + assert false; + } + } +} From fb23404f2029b6b20e7686b68d0676a9d7ff9fa4 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 8 Dec 2021 22:46:00 +0100 Subject: [PATCH 02/27] Update steamwarci.yml --- steamwarci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/steamwarci.yml b/steamwarci.yml index d3e2564..e630fae 100644 --- a/steamwarci.yml +++ b/steamwarci.yml @@ -3,6 +3,7 @@ build: - "cp ~/gradle.properties ." - "chmod u+x build.gradle" - "./gradlew buildProject" + - "./gradlew test" artifacts: "/binarys/spigotcore.jar": "build/libs/spigotcore.jar" From 58221d50c26507685741ba3de24b9ccd04fa778d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 8 Dec 2021 23:20:58 +0100 Subject: [PATCH 03/27] Add CommandPartTest --- .../src/de/steamwar/command/CommandPart.java | 29 +++++++- .../de/steamwar/command/CommandPartTest.java | 73 +++++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index bcb6c3f..720ebde 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -85,22 +85,43 @@ public class CommandPart { } if (optional != null) { current.add(typeMapper.map(commandSender, EMPTY_ARRAY, optional)); - next.generateArgumentArray(current, commandSender, args, startIndex); + if (next != null) { + next.generateArgumentArray(current, commandSender, args, startIndex); + } return; } current.add(validArgument.value); - next.generateArgumentArray(current, commandSender, args, startIndex + 1); + if (next != null) { + next.generateArgumentArray(current, commandSender, args, startIndex + 1); + } } void generateTabComplete(List current, CommandSender commandSender, String[] args, int startIndex) { + if (args.length < startIndex) { + CheckArgumentResult checkArgumentResult = checkArgument(GuardCheckType.TAB_COMPLETE, commandSender, args, startIndex); + if (checkArgumentResult.success && next != null) { + next.generateTabComplete(current, commandSender, args, startIndex + 1); + } + return; + } + List strings = typeMapper.tabCompletes(commandSender, Arrays.copyOf(args, startIndex), args[startIndex]); + if (strings != null) { + current.addAll(strings); + } + if (optional != null && next != null) { + next.generateTabComplete(current, commandSender, args, startIndex); + } } private CheckArgumentResult checkArgument(GuardCheckType guardCheckType, CommandSender commandSender, String[] args, int index) { try { - Object value = typeMapper.map(commandSender, Arrays.copyOf(args, index - 1), args[index]); + Object value = typeMapper.map(commandSender, Arrays.copyOf(args, index), args[index]); + if (value == null) { + return new CheckArgumentResult(false, null); + } if (guard != null) { - GuardResult guardResult = guard.guard(commandSender, GuardCheckType.TAB_COMPLETE, Arrays.copyOf(args, index - 1), args[index]); + GuardResult guardResult = guard.guard(commandSender, guardCheckType, Arrays.copyOf(args, index), args[index]); switch (guardResult) { case ALLOWED: return new CheckArgumentResult(true, value); diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java new file mode 100644 index 0000000..6d86763 --- /dev/null +++ b/SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java @@ -0,0 +1,73 @@ +/* + * 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 de.steamwar.TestCommandSender; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +public class CommandPartTest { + + private CommandPart commandPart; + + @Before + public void setUp() throws Exception { + commandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, false); + } + + @Test + public void testCommandPartTabCompleteNoArguments() { + List tabComplete = new ArrayList<>(); + commandPart.generateTabComplete(tabComplete, new TestCommandSender(), new String[]{""}, 0); + assertThat(tabComplete.size(), is(2)); + assertThat(tabComplete.get(0), is("hello")); + assertThat(tabComplete.get(1), is("world")); + } + + @Test(expected = CommandParseException.class) + public void testCommandExecuteInvalidArgument() { + commandPart.generateArgumentArray(new ArrayList<>(), new TestCommandSender(), new String[]{""}, 0); + } + + @Test + public void testCommandExecuteValidArgument() { + List argumentArray = new ArrayList<>(); + commandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(String.class)); + assertThat(argumentArray.get(0), is("hello")); + } + + @Test + public void testCommandExecuteValidOtherArgument() { + List argumentArray = new ArrayList<>(); + commandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"world"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(String.class)); + assertThat(argumentArray.get(0), is("world")); + } +} From 93156a097694feab1c1d40a9855eea9f5c1c3050 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 8 Dec 2021 23:32:33 +0100 Subject: [PATCH 04/27] Add some more Tests --- .../src/de/steamwar/command/CommandPart.java | 6 +- .../de/steamwar/command/CommandPartTest.java | 73 ----------- .../command/SimpleCommandPartTest.java | 121 ++++++++++++++++++ 3 files changed, 124 insertions(+), 76 deletions(-) delete mode 100644 SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java create mode 100644 SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index 720ebde..27762e4 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -37,8 +37,8 @@ public class CommandPart { private TypeMapper typeMapper; private GuardChecker guard; - private Class varArgType = null; - private String optional = null; + private Class varArgType; + private String optional; private boolean help; private CommandPart next = null; @@ -97,7 +97,7 @@ public class CommandPart { } void generateTabComplete(List current, CommandSender commandSender, String[] args, int startIndex) { - if (args.length < startIndex) { + if (args.length - 1 > startIndex) { CheckArgumentResult checkArgumentResult = checkArgument(GuardCheckType.TAB_COMPLETE, commandSender, args, startIndex); if (checkArgumentResult.success && next != null) { next.generateTabComplete(current, commandSender, args, startIndex + 1); diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java deleted file mode 100644 index 6d86763..0000000 --- a/SpigotCore_Main/testsrc/de/steamwar/command/CommandPartTest.java +++ /dev/null @@ -1,73 +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 de.steamwar.TestCommandSender; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; - -public class CommandPartTest { - - private CommandPart commandPart; - - @Before - public void setUp() throws Exception { - commandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, false); - } - - @Test - public void testCommandPartTabCompleteNoArguments() { - List tabComplete = new ArrayList<>(); - commandPart.generateTabComplete(tabComplete, new TestCommandSender(), new String[]{""}, 0); - assertThat(tabComplete.size(), is(2)); - assertThat(tabComplete.get(0), is("hello")); - assertThat(tabComplete.get(1), is("world")); - } - - @Test(expected = CommandParseException.class) - public void testCommandExecuteInvalidArgument() { - commandPart.generateArgumentArray(new ArrayList<>(), new TestCommandSender(), new String[]{""}, 0); - } - - @Test - public void testCommandExecuteValidArgument() { - List argumentArray = new ArrayList<>(); - commandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello"}, 0); - assertThat(argumentArray.size(), is(1)); - assertThat(argumentArray.get(0), instanceOf(String.class)); - assertThat(argumentArray.get(0), is("hello")); - } - - @Test - public void testCommandExecuteValidOtherArgument() { - List argumentArray = new ArrayList<>(); - commandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"world"}, 0); - assertThat(argumentArray.size(), is(1)); - assertThat(argumentArray.get(0), instanceOf(String.class)); - assertThat(argumentArray.get(0), is("world")); - } -} diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java new file mode 100644 index 0000000..1d7b99f --- /dev/null +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java @@ -0,0 +1,121 @@ +/* + * 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 de.steamwar.TestCommandSender; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +public class SimpleCommandPartTest { + + private CommandPart stringCommandPart; + private CommandPart intCommandPart; + private CommandPart chainedCommandPart; + + @Before + public void setUp() throws Exception { + stringCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, false); + intCommandPart = new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, true); + + chainedCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, false); + chainedCommandPart.setNext(new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, true)); + } + + @Test + public void testCommandPartTabCompleteNoArguments() { + List tabComplete = new ArrayList<>(); + stringCommandPart.generateTabComplete(tabComplete, new TestCommandSender(), new String[]{""}, 0); + assertThat(tabComplete.size(), is(2)); + assertThat(tabComplete.get(0), is("hello")); + assertThat(tabComplete.get(1), is("world")); + } + + @Test(expected = CommandParseException.class) + public void testCommandExecuteInvalidArgument() { + stringCommandPart.generateArgumentArray(new ArrayList<>(), new TestCommandSender(), new String[]{""}, 0); + } + + @Test + public void testCommandExecuteValidArgument() { + List argumentArray = new ArrayList<>(); + stringCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(String.class)); + assertThat(argumentArray.get(0), is("hello")); + } + + @Test + public void testCommandExecuteValidOtherArgument() { + List argumentArray = new ArrayList<>(); + stringCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"world"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(String.class)); + assertThat(argumentArray.get(0), is("world")); + } + + @Test(expected = CommandParseException.class) + public void testCommandExecuteNonNumberArgument() { + intCommandPart.generateArgumentArray(new ArrayList<>(), new TestCommandSender(), new String[]{"world"}, 0); + } + + @Test + public void testCommandExecuteValidNumberArgument() { + List argumentArray = new ArrayList<>(); + intCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"0"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(int.class)); + assertThat(argumentArray.get(0), is(0)); + } + + @Test + public void testChainedCommandExecuteValidArgument() { + List argumentArray = new ArrayList<>(); + chainedCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello", "0"}, 0); + assertThat(argumentArray.size(), is(2)); + assertThat(argumentArray.get(0), instanceOf(String.class)); + assertThat(argumentArray.get(0), is("hello")); + assertThat(argumentArray.get(1), instanceOf(int.class)); + assertThat(argumentArray.get(1), is(0)); + } + + @Test + public void testChainedCommandTabComplete() { + List tabCompletes = new ArrayList<>(); + chainedCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{""}, 0); + assertThat(tabCompletes.size(), is(2)); + assertThat(tabCompletes.get(0), is("hello")); + assertThat(tabCompletes.get(1), is("world")); + } + + @Test + public void testChainedCommandTabCompleteOther() { + List tabCompletes = new ArrayList<>(); + chainedCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{"hello", ""}, 0); + System.out.println(tabCompletes); + assertThat(tabCompletes.size(), is(0)); + } +} From 86ef8e2773272e07052e45f3406152492a8dc5bb Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 13:24:28 +0100 Subject: [PATCH 05/27] Add some more Tests Add CommandPart.checkGuard --- .../src/de/steamwar/command/CommandPart.java | 77 ++++++++++++++----- .../steamwar/command/CommandRegistering.java | 2 + .../command/SimpleCommandPartTest.java | 37 ++++++++- 3 files changed, 92 insertions(+), 24 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index 27762e4..2c3d394 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -39,11 +39,11 @@ public class CommandPart { private GuardChecker guard; private Class varArgType; private String optional; - private boolean help; + private GuardCheckType guardCheckType; private CommandPart next = null; - CommandPart(TypeMapper typeMapper, GuardChecker guard, Class varArgType, String optional, boolean help) { + public CommandPart(TypeMapper typeMapper, GuardChecker guard, Class varArgType, String optional, GuardCheckType guardCheckType) { this.typeMapper = typeMapper; this.guard = guard; if (optional != null && varArgType != null) { @@ -51,17 +51,17 @@ public class CommandPart { } this.varArgType = varArgType; this.optional = optional; - this.help = help; + this.guardCheckType = guardCheckType; } - void setNext(CommandPart next) { + public void setNext(CommandPart next) { if (varArgType != null) { throw new IllegalArgumentException("There can't be a next part if this is a vararg part!"); } this.next = next; } - void generateArgumentArray(List current, CommandSender commandSender, String[] args, int startIndex) { + public void generateArgumentArray(List current, CommandSender commandSender, String[] args, int startIndex) { if (startIndex >= args.length) { return; } @@ -69,7 +69,7 @@ public class CommandPart { if (varArgType != null) { Object array = Array.newInstance(varArgType, args.length - startIndex); for (int i = startIndex; i < args.length; i++) { - CheckArgumentResult validArgument = checkArgument(help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, commandSender, args, i); + CheckArgumentResult validArgument = checkArgument(null, commandSender, args, i); if (!validArgument.success) { throw new CommandParseException(); } @@ -79,7 +79,7 @@ public class CommandPart { return; } - CheckArgumentResult validArgument = checkArgument(help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, commandSender, args, startIndex); + CheckArgumentResult validArgument = checkArgument(null, commandSender, args, startIndex); if (!validArgument.success && optional == null) { throw new CommandParseException(); } @@ -96,7 +96,40 @@ public class CommandPart { } } - void generateTabComplete(List current, CommandSender commandSender, String[] args, int startIndex) { + public boolean guardCheck(CommandSender commandSender, String[] args, int startIndex) { + if (varArgType != null) { + for (int i = startIndex; i < args.length; i++) { + GuardResult guardResult = checkGuard(guardCheckType, commandSender, args, i); + if (guardResult == GuardResult.DENIED) { + throw new CommandNoHelpException(); + } + if (guardResult == GuardResult.DENIED_WITH_HELP) { + return false; + } + } + return true; + } + + GuardResult guardResult = checkGuard(guardCheckType, commandSender, args, startIndex); + if (guardResult == GuardResult.DENIED) { + if (optional != null && next != null) { + return next.guardCheck(commandSender, args, startIndex); + } + throw new CommandNoHelpException(); + } + if (guardResult == GuardResult.DENIED_WITH_HELP) { + if (optional != null && next != null) { + return next.guardCheck(commandSender, args, startIndex); + } + return false; + } + if (next != null) { + return next.guardCheck(commandSender, args, startIndex + 1); + } + return true; + } + + public void generateTabComplete(List current, CommandSender commandSender, String[] args, int startIndex) { if (args.length - 1 > startIndex) { CheckArgumentResult checkArgumentResult = checkArgument(GuardCheckType.TAB_COMPLETE, commandSender, args, startIndex); if (checkArgumentResult.success && next != null) { @@ -120,21 +153,25 @@ public class CommandPart { if (value == null) { return new CheckArgumentResult(false, null); } - if (guard != null) { - GuardResult guardResult = guard.guard(commandSender, guardCheckType, Arrays.copyOf(args, index), args[index]); - switch (guardResult) { - case ALLOWED: - return new CheckArgumentResult(true, value); - case DENIED: - throw new CommandNoHelpException(); - case DENIED_WITH_HELP: - default: - return new CheckArgumentResult(false, null); - } + GuardResult guardResult = checkGuard(guardCheckType, commandSender, args, index); + switch (guardResult) { + case ALLOWED: + return new CheckArgumentResult(true, value); + case DENIED: + throw new CommandNoHelpException(); + case DENIED_WITH_HELP: + default: + return new CheckArgumentResult(false, null); } - return new CheckArgumentResult(true, value); } catch (Exception e) { return new CheckArgumentResult(false, null); } } + + private GuardResult checkGuard(GuardCheckType guardCheckType, CommandSender commandSender, String[] args, int index) { + if (guard != null && guardCheckType != null) { + return guard.guard(commandSender, guardCheckType, Arrays.copyOf(args, index), args[index]); + } + return GuardResult.ALLOWED; + } } diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java b/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java index 8cbf59f..143ea2a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java @@ -19,6 +19,7 @@ package de.steamwar.command; +import lombok.experimental.UtilityClass; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandMap; @@ -27,6 +28,7 @@ import org.bukkit.command.SimpleCommandMap; import java.lang.reflect.Field; import java.util.Map; +@UtilityClass class CommandRegistering { private static final CommandMap commandMap; diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java index 1d7b99f..d734d71 100644 --- a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java @@ -36,13 +36,17 @@ public class SimpleCommandPartTest { private CommandPart intCommandPart; private CommandPart chainedCommandPart; + private CommandPart simpleGuardPart; + @Before public void setUp() throws Exception { - stringCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, false); - intCommandPart = new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, true); + stringCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, GuardCheckType.COMMAND); + intCommandPart = new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, GuardCheckType.COMMAND); - chainedCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, false); - chainedCommandPart.setNext(new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, true)); + chainedCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, GuardCheckType.COMMAND); + chainedCommandPart.setNext(new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, GuardCheckType.COMMAND)); + + simpleGuardPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), (commandSender, guardCheckType, previousArguments, s) -> s.equals("hello") ? GuardResult.DENIED : GuardResult.ALLOWED, null, null, GuardCheckType.COMMAND); } @Test @@ -118,4 +122,29 @@ public class SimpleCommandPartTest { System.out.println(tabCompletes); assertThat(tabCompletes.size(), is(0)); } + + @Test + public void testGuardCommandExecute() { + List argumentArray = new ArrayList<>(); + simpleGuardPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello"}, 0); + assertThat(argumentArray.size(), is(1)); + } + + @Test(expected = CommandNoHelpException.class) + public void testGuardGuardCheck() { + simpleGuardPart.guardCheck(new TestCommandSender(), new String[]{"hello"}, 0); + } + + @Test + public void testGuardCommandExecuteValid() { + List argumentArray = new ArrayList<>(); + simpleGuardPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"world"}, 0); + assertThat(argumentArray.size(), is(1)); + } + + @Test + public void testGuardGuardCheckValid() { + boolean guardResult = simpleGuardPart.guardCheck(new TestCommandSender(), new String[]{"world"}, 0); + assertThat(guardResult, is(true)); + } } From 2bc15adfdabb7b2539c9bb2dd32881d48a6ff46a Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 14:53:48 +0100 Subject: [PATCH 06/27] Fix CommandPart.init --- SpigotCore_Main/src/de/steamwar/command/CommandPart.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index 2c3d394..b396f71 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -44,6 +44,9 @@ public class CommandPart { private CommandPart next = null; public CommandPart(TypeMapper typeMapper, GuardChecker guard, Class varArgType, String optional, GuardCheckType guardCheckType) { + if (guardCheckType == GuardCheckType.TAB_COMPLETE) { + throw new IllegalArgumentException("Tab complete is not allowed as a guard check type!"); + } this.typeMapper = typeMapper; this.guard = guard; if (optional != null && varArgType != null) { From 7d94d8dd6ceff2f4cb5a793c1213f61afd2e3cb7 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 15:09:07 +0100 Subject: [PATCH 07/27] Fix CommandPart.generateTabComplete for varArg Parameter --- .../src/de/steamwar/command/CommandPart.java | 14 ++++++ .../command/SimpleCommandPartTest.java | 46 +++++++++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index b396f71..b7960ed 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -133,6 +133,20 @@ public class CommandPart { } public void generateTabComplete(List current, CommandSender commandSender, String[] args, int startIndex) { + if (varArgType != null) { + for (int i = startIndex; i < args.length - 1; i++) { + CheckArgumentResult validArgument = checkArgument(null, commandSender, args, i); + if (!validArgument.success) { + return; + } + } + List strings = typeMapper.tabCompletes(commandSender, Arrays.copyOf(args, args.length - 1), args[args.length - 1]); + if (strings != null) { + current.addAll(strings); + } + return; + } + if (args.length - 1 > startIndex) { CheckArgumentResult checkArgumentResult = checkArgument(GuardCheckType.TAB_COMPLETE, commandSender, args, startIndex); if (checkArgumentResult.success && next != null) { diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java index d734d71..47503d2 100644 --- a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java @@ -27,14 +27,14 @@ import java.util.ArrayList; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; public class SimpleCommandPartTest { private CommandPart stringCommandPart; private CommandPart intCommandPart; private CommandPart chainedCommandPart; + private CommandPart varArgCommandPart; private CommandPart simpleGuardPart; @@ -46,6 +46,8 @@ public class SimpleCommandPartTest { chainedCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, GuardCheckType.COMMAND); chainedCommandPart.setNext(new CommandPart(SWCommandUtils.MAPPER_FUNCTIONS.get("int"), null, null, null, GuardCheckType.COMMAND)); + varArgCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, String.class, null, GuardCheckType.COMMAND); + simpleGuardPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), (commandSender, guardCheckType, previousArguments, s) -> s.equals("hello") ? GuardResult.DENIED : GuardResult.ALLOWED, null, null, GuardCheckType.COMMAND); } @@ -119,10 +121,48 @@ public class SimpleCommandPartTest { public void testChainedCommandTabCompleteOther() { List tabCompletes = new ArrayList<>(); chainedCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{"hello", ""}, 0); - System.out.println(tabCompletes); assertThat(tabCompletes.size(), is(0)); } + @Test + public void testVarArgsCommandTabComplete() { + List tabCompletes = new ArrayList<>(); + varArgCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{"hello"}, 0); + assertThat(tabCompletes.size(), is(2)); + assertThat(tabCompletes.get(0), is("hello")); + assertThat(tabCompletes.get(1), is("world")); + } + + @Test + public void testVarArgsCommandTabCompleteDeeper() { + List tabCompletes = new ArrayList<>(); + varArgCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{"hello", "world", "hello", "world"}, 0); + System.out.println(tabCompletes); + assertThat(tabCompletes.size(), is(2)); + assertThat(tabCompletes.get(0), is("hello")); + assertThat(tabCompletes.get(1), is("world")); + } + + @Test + public void testVarArgsCommandArgumentParsing() { + List argumentArray = new ArrayList<>(); + varArgCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(String[].class)); + assertThat((String[]) argumentArray.get(0), arrayWithSize(1)); + assertThat((String[]) argumentArray.get(0), is(new String[]{"hello"})); + } + + @Test + public void testVarArgsCommandArgumentParsingDeeper() { + List argumentArray = new ArrayList<>(); + varArgCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello", "world", "hello", "world"}, 0); + assertThat(argumentArray.size(), is(1)); + assertThat(argumentArray.get(0), instanceOf(String[].class)); + assertThat((String[]) argumentArray.get(0), arrayWithSize(4)); + assertThat((String[]) argumentArray.get(0), is(new String[]{"hello", "world", "hello", "world"})); + } + @Test public void testGuardCommandExecute() { List argumentArray = new ArrayList<>(); From b5f9284bb571b63fdfe086db1a78c510eac45624 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 15:23:46 +0100 Subject: [PATCH 08/27] Fix CommandPart.generateTabComplete for optional arguments --- .../src/de/steamwar/command/CommandPart.java | 29 +++++++--- .../src/de/steamwar/command/TypeMapper.java | 3 ++ .../command/SimpleCommandPartTest.java | 53 +++++++++++++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index b7960ed..e6dbf8c 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -44,17 +44,13 @@ public class CommandPart { private CommandPart next = null; public CommandPart(TypeMapper typeMapper, GuardChecker guard, Class varArgType, String optional, GuardCheckType guardCheckType) { - if (guardCheckType == GuardCheckType.TAB_COMPLETE) { - throw new IllegalArgumentException("Tab complete is not allowed as a guard check type!"); - } this.typeMapper = typeMapper; this.guard = guard; - if (optional != null && varArgType != null) { - throw new IllegalArgumentException("A vararg part can't have an optional part!"); - } this.varArgType = varArgType; this.optional = optional; this.guardCheckType = guardCheckType; + + validatePart(); } public void setNext(CommandPart next) { @@ -64,9 +60,26 @@ public class CommandPart { this.next = next; } + private void validatePart() { + if (guardCheckType == GuardCheckType.TAB_COMPLETE) { + throw new IllegalArgumentException("Tab complete is not allowed as a guard check type!"); + } + if (optional != null && varArgType != null) { + throw new IllegalArgumentException("A vararg part can't have an optional part!"); + } + + if (optional != null) { + try { + typeMapper.map(null, EMPTY_ARRAY, optional); + } catch (Exception e) { + throw new IllegalArgumentException("The optional part is not valid!"); + } + } + } + public void generateArgumentArray(List current, CommandSender commandSender, String[] args, int startIndex) { if (startIndex >= args.length) { - return; + throw new CommandParseException(); } if (varArgType != null) { @@ -86,7 +99,7 @@ public class CommandPart { if (!validArgument.success && optional == null) { throw new CommandParseException(); } - if (optional != null) { + if (!validArgument.success) { current.add(typeMapper.map(commandSender, EMPTY_ARRAY, optional)); if (next != null) { next.generateArgumentArray(current, commandSender, args, startIndex); diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java index dce1882..bc794fb 100644 --- a/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java +++ b/SpigotCore_Main/src/de/steamwar/command/TypeMapper.java @@ -24,6 +24,9 @@ import org.bukkit.command.CommandSender; import java.util.List; public interface TypeMapper { + /** + * The CommandSender can be null! + */ default T map(CommandSender commandSender, String[] previousArguments, String s) { return map(previousArguments, s); } diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java index 47503d2..a9474a0 100644 --- a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandPartTest.java @@ -38,6 +38,8 @@ public class SimpleCommandPartTest { private CommandPart simpleGuardPart; + private CommandPart optionalCommandPart; + @Before public void setUp() throws Exception { stringCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, null, GuardCheckType.COMMAND); @@ -49,6 +51,9 @@ public class SimpleCommandPartTest { varArgCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, String.class, null, GuardCheckType.COMMAND); simpleGuardPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), (commandSender, guardCheckType, previousArguments, s) -> s.equals("hello") ? GuardResult.DENIED : GuardResult.ALLOWED, null, null, GuardCheckType.COMMAND); + + optionalCommandPart = new CommandPart(SWCommandUtils.createMapper("hello", "world"), null, null, "hello", GuardCheckType.COMMAND); + optionalCommandPart.setNext(new CommandPart(SWCommandUtils.createMapper("hello2", "world2"), null, null, null, GuardCheckType.COMMAND)); } @Test @@ -187,4 +192,52 @@ public class SimpleCommandPartTest { boolean guardResult = simpleGuardPart.guardCheck(new TestCommandSender(), new String[]{"world"}, 0); assertThat(guardResult, is(true)); } + + @Test + public void testOptionalCommandPartTabComplete() { + List tabCompletes = new ArrayList<>(); + optionalCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{""}, 0); + assertThat(tabCompletes.size(), is(4)); + assertThat(tabCompletes.get(0), is("hello")); + assertThat(tabCompletes.get(1), is("world")); + assertThat(tabCompletes.get(2), is("hello2")); + assertThat(tabCompletes.get(3), is("world2")); + } + + @Test + public void testOptionalCommandPartTabCompleteSecond() { + List tabCompletes = new ArrayList<>(); + optionalCommandPart.generateTabComplete(tabCompletes, new TestCommandSender(), new String[]{"hello", ""}, 0); + assertThat(tabCompletes.size(), is(2)); + assertThat(tabCompletes.get(0), is("hello2")); + assertThat(tabCompletes.get(1), is("world2")); + } + + @Test(expected = CommandParseException.class) + public void testOptionalCommandPartExecution() { + optionalCommandPart.generateArgumentArray(new ArrayList<>(), new TestCommandSender(), new String[]{""}, 0); + } + + @Test + public void testOptionalCommandPartExecutionValid() { + List argumentArray = new ArrayList<>(); + optionalCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"hello2"}, 0); + assertThat(argumentArray.size(), is(2)); + assertThat(argumentArray.get(0), is("hello")); + assertThat(argumentArray.get(1), is("hello2")); + } + + @Test(expected = CommandParseException.class) + public void testOptionalCommandPartExecutionInvalid() { + optionalCommandPart.generateArgumentArray(new ArrayList<>(), new TestCommandSender(), new String[]{"hello"}, 0); + } + + @Test + public void testOptionalCommandPartExecutionFullyValid() { + List argumentArray = new ArrayList<>(); + optionalCommandPart.generateArgumentArray(argumentArray, new TestCommandSender(), new String[]{"world", "hello2"}, 0); + assertThat(argumentArray.size(), is(2)); + assertThat(argumentArray.get(0), is("world")); + assertThat(argumentArray.get(1), is("hello2")); + } } From 2bac163e578211f4ccf9e5f952a82aa35c8182bb Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 15:26:31 +0100 Subject: [PATCH 09/27] Update SWCommand.OptionalValue --- SpigotCore_Main/src/de/steamwar/command/SWCommand.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 7126fe8..0558dad 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -361,6 +361,9 @@ public abstract class SWCommand { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PARAMETER}) protected @interface OptionalValue { - String defaultValue(); // Will pe parsed against the TypeMapper specified by the parameter or annotation + /** + * Will pe parsed against the TypeMapper specified by the parameter or annotation. + */ + String value(); } } From cd90cba7d5d437174bf4cc2f81540251bf339e2a Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 16:38:58 +0100 Subject: [PATCH 10/27] Update SWCommandUtils SteamwarUser mapper --- .../de/steamwar/command/SWCommandUtils.java | 18 ++++++++++++------ .../src/de/steamwar/sql/SteamwarUser.java | 11 +++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 0ee8562..0d95f8c 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -72,17 +72,23 @@ public class SWCommandUtils { if (s.equals("a") || s.equals("adventure") || s.equals("2")) return GameMode.ADVENTURE; return null; }, s -> Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "spectator", "3", "a", "adventure", "2"))); - MAPPER_FUNCTIONS.put(SteamwarUser.class.getTypeName(), createMapper(SteamwarUser::get, s -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()))); - MAPPER_FUNCTIONS.put(SchematicNode.class.getTypeName(), new TypeMapper() { - @Override - public List tabCompletes(CommandSender commandSender, String[] strings, String s) { - return SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); + MAPPER_FUNCTIONS.put(SteamwarUser.class.getTypeName(), createMapper(SteamwarUser::get, s -> { + if (s.length() < 1) { + return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); } - + List steamwarUsers = SteamwarUser.startsWithName(s); + return steamwarUsers.stream().map(SteamwarUser::getUserName).limit(40).collect(Collectors.toList()); + })); + MAPPER_FUNCTIONS.put(SchematicNode.class.getTypeName(), new TypeMapper() { @Override public SchematicNode map(CommandSender commandSender, String[] previousArguments, String s) { return SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); } + + @Override + public List tabCompletes(CommandSender commandSender, String[] strings, String s) { + return SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); + } }); } diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index 1a7ed6f..cc958cf 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -32,6 +32,7 @@ public class SteamwarUser { private static final SQL.Statement getId = new SQL.Statement("SELECT * FROM UserData WHERE id = ?"); private static final SQL.Statement getUUID = new SQL.Statement("SELECT * FROM UserData WHERE UUID = ?"); private static final SQL.Statement getName = new SQL.Statement("SELECT * FROM UserData WHERE lower(UserName) = ?"); + private static final SQL.Statement startWithName = new SQL.Statement("SELECT * FROM UserData WHERE lower(UserName) LIKE ?"); private static final Map byUUID = new HashMap<>(); private static final Map byName = new HashMap<>(); @@ -93,6 +94,16 @@ public class SteamwarUser { return bedrock; } + public static List startsWithName(String userName){ + return startWithName.select(rs -> { + List steamwarUsers = new ArrayList<>(); + while (rs.next()) { + steamwarUsers.add(new SteamwarUser(rs)); + } + return steamwarUsers; + }, userName.toLowerCase() + "%"); + } + public static SteamwarUser get(String userName){ SteamwarUser user = byName.get(userName.toLowerCase()); if(user == null) From 779199f05850505e840722b7d2ff8e6797f3b1e0 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 17:27:27 +0100 Subject: [PATCH 11/27] Update SWCommandUtils SteamwarUser mapper --- .../de/steamwar/command/SWCommandUtils.java | 6 +--- .../src/de/steamwar/sql/SteamwarUser.java | 31 ++++++++++++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 0d95f8c..aa5d27b 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -23,15 +23,11 @@ import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; 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.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.*; import java.util.function.BiFunction; @@ -76,7 +72,7 @@ public class SWCommandUtils { if (s.length() < 1) { return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); } - List steamwarUsers = SteamwarUser.startsWithName(s); + List steamwarUsers = SteamwarUser.getByPrefix(s); return steamwarUsers.stream().map(SteamwarUser::getUserName).limit(40).collect(Collectors.toList()); })); MAPPER_FUNCTIONS.put(SchematicNode.class.getTypeName(), new TypeMapper() { diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index cc958cf..9c3115b 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -26,6 +26,7 @@ import org.bukkit.entity.Player; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; +import java.util.stream.Collectors; public class SteamwarUser { @@ -37,12 +38,14 @@ public class SteamwarUser { private static final Map byUUID = new HashMap<>(); private static final Map byName = new HashMap<>(); private static final Map byId = new HashMap<>(); + private static final Map> byPrefix = new HashMap<>(); static{ Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { byId.clear(); byName.clear(); byUUID.clear(); + byPrefix.clear(); }, 72000, 72000); } @@ -94,14 +97,26 @@ public class SteamwarUser { return bedrock; } - public static List startsWithName(String userName){ - return startWithName.select(rs -> { - List steamwarUsers = new ArrayList<>(); - while (rs.next()) { - steamwarUsers.add(new SteamwarUser(rs)); - } - return steamwarUsers; - }, userName.toLowerCase() + "%"); + public static List getByPrefix(String userName){ + if (userName.length() < 2) { + return new ArrayList<>(); + } + List users = byPrefix.get(userName.toLowerCase().substring(0, 1)); + if (users == null) { + users = startWithName.select(rs -> { + List steamwarUsers = new ArrayList<>(); + while (rs.next()) { + String name = rs.getString("UserName"); + if (byName.containsKey(name)) { + steamwarUsers.add(byName.get(name)); + } else { + steamwarUsers.add(new SteamwarUser(rs)); + } + } + return steamwarUsers; + }, userName.toLowerCase() + "%"); + } + return users.stream().filter(user -> user.getUserName().toLowerCase().startsWith(userName.toLowerCase())).collect(Collectors.toList()); } public static SteamwarUser get(String userName){ From 4366a1849685243131d215f811840e7bcb217b75 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 17:27:54 +0100 Subject: [PATCH 12/27] Update SWCommandUtils SteamwarUser mapper --- SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index 9c3115b..d07ba7b 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -115,6 +115,7 @@ public class SteamwarUser { } return steamwarUsers; }, userName.toLowerCase() + "%"); + byPrefix.put(userName.toLowerCase().substring(0, 1), users); } return users.stream().filter(user -> user.getUserName().toLowerCase().startsWith(userName.toLowerCase())).collect(Collectors.toList()); } From f964b4541cbc1b196df9f2a6f90bdd1168f2fd47 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 18:00:31 +0100 Subject: [PATCH 13/27] Update SWCommandUtils SteamwarUser mapper --- SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index d07ba7b..cd4ba0f 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -98,7 +98,7 @@ public class SteamwarUser { } public static List getByPrefix(String userName){ - if (userName.length() < 2) { + if (userName.length() < 1) { return new ArrayList<>(); } List users = byPrefix.get(userName.toLowerCase().substring(0, 1)); From 17fdb34473febbf5f2ef2898e82b519a8953218f Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 18:00:44 +0100 Subject: [PATCH 14/27] Update SWCommandUtils SteamwarUser mapper --- SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index cd4ba0f..d3c124e 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -98,7 +98,7 @@ public class SteamwarUser { } public static List getByPrefix(String userName){ - if (userName.length() < 1) { + if (userName.isEmpty()) { return new ArrayList<>(); } List users = byPrefix.get(userName.toLowerCase().substring(0, 1)); From cd8d2a8b42a66000e095d2e7a7a1f47b01be9da3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 18:01:49 +0100 Subject: [PATCH 15/27] Update SWCommandUtils SteamwarUser mapper --- SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index d3c124e..9188cb7 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -107,11 +107,9 @@ public class SteamwarUser { List steamwarUsers = new ArrayList<>(); while (rs.next()) { String name = rs.getString("UserName"); - if (byName.containsKey(name)) { - steamwarUsers.add(byName.get(name)); - } else { - steamwarUsers.add(new SteamwarUser(rs)); - } + SteamwarUser user = byName.get(name.toLowerCase()); + if (user == null) user = new SteamwarUser(rs); + steamwarUsers.add(user); } return steamwarUsers; }, userName.toLowerCase() + "%"); From 415a002cad835480af411d214f877a8503cdfaf9 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 19:19:17 +0100 Subject: [PATCH 16/27] Update SWCommand system to CommandPart System for better usages and extension possibilities --- .../src/de/steamwar/command/SWCommand.java | 3 +- .../de/steamwar/command/SWCommandUtils.java | 116 +++++++++- .../src/de/steamwar/command/SubCommand.java | 211 ++++-------------- .../steamwar/command/SimpleCommandTest.java | 1 + 4 files changed, 147 insertions(+), 184 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java index 0558dad..98d742a 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommand.java @@ -174,8 +174,7 @@ public abstract class SWCommand { if (compare != 0) { return compare; } else { - return Integer.compare(o1.varArgType != null ? Integer.MAX_VALUE : o1.arguments.length, - o2.varArgType != null ? Integer.MAX_VALUE : o2.arguments.length); + return Integer.compare(o1.comparableValue, o2.comparableValue); } }); commandHelpList.sort((o1, o2) -> { diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index aa5d27b..fa6c3f3 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -29,6 +29,7 @@ import org.bukkit.entity.Player; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; @@ -43,15 +44,6 @@ 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(); - }, s -> Collections.emptyList()); - - static final BiFunction>, String, Enum> ENUM_MAPPER = (enumClass, s) -> { - Enum[] enums = enumClass.getEnumConstants(); - return Arrays.stream(enums).filter(e -> e.name().equalsIgnoreCase(s)).findFirst().orElse(null); - }; - static { addMapper(boolean.class, Boolean.class, createMapper(Boolean::parseBoolean, s -> Arrays.asList("true", "false"))); addMapper(float.class, Float.class, createMapper(numberMapper(Float::parseFloat), numberCompleter(Float::parseFloat))); @@ -93,6 +85,93 @@ public class SWCommandUtils { MAPPER_FUNCTIONS.put(alternativeClazz.getTypeName(), mapper); } + static CommandPart generateCommandPart(boolean help, String[] subCommand, Parameter[] parameters, Map> localTypeMapper, Map localGuardChecker) { + CommandPart current = null; + for (String s : subCommand) { + CommandPart commandPart = new CommandPart(createMapper(s), null, null, null, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND); + if (current != null) { + current.setNext(commandPart); + } + current = commandPart; + } + for (int i = 1; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + TypeMapper typeMapper = getTypeMapper(parameter, localTypeMapper); + GuardChecker guardChecker = getGuardChecker(parameter, localGuardChecker); + Class varArgType = parameter.isVarArgs() ? parameter.getType().getComponentType() : null; + SWCommand.OptionalValue optionalValue = parameter.getAnnotation(SWCommand.OptionalValue.class); + + CommandPart commandPart = new CommandPart(typeMapper, guardChecker, varArgType, optionalValue != null ? optionalValue.value() : null, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND); + if (current != null) { + current.setNext(commandPart); + } + current = commandPart; + } + return current; + } + + static TypeMapper getTypeMapper(Parameter parameter, Map> localTypeMapper) { + Class clazz = parameter.getType(); + if (parameter.isVarArgs()) { + clazz = clazz.getComponentType(); + } + + SWCommand.ClassMapper classMapper = clazz.getAnnotation(SWCommand.ClassMapper.class); + SWCommand.Mapper mapper = clazz.getAnnotation(SWCommand.Mapper.class); + if (clazz.isEnum() && classMapper == null && mapper == null && !MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) { + return createEnumMapper((Class>) clazz); + } + + String name = clazz.getTypeName(); + if (classMapper != null) { + name = classMapper.value().getTypeName(); + } else if (mapper != null) { + name = mapper.value(); + } else { + SWCommand.StaticValue staticValue = parameter.getAnnotation(SWCommand.StaticValue.class); + if (staticValue != null && parameter.getType() == String.class) { + return createMapper(staticValue.value()); + } + } + TypeMapper typeMapper = localTypeMapper.getOrDefault(name, MAPPER_FUNCTIONS.getOrDefault(name, null)); + if (typeMapper == null) { + throw new IllegalArgumentException("No mapper found for " + name); + } + return typeMapper; + } + + static GuardChecker getGuardChecker(Parameter parameter, Map localGuardChecker) { + Class clazz = parameter.getType(); + if (parameter.isVarArgs()) { + clazz = clazz.getComponentType(); + } + + SWCommand.ClassGuard classGuard = clazz.getAnnotation(SWCommand.ClassGuard.class); + if (classGuard != null) { + if (classGuard.value() != null) { + return getGuardChecker(classGuard.value().getTypeName(), localGuardChecker); + } + return getGuardChecker(clazz.getTypeName(), localGuardChecker); + } + + SWCommand.Guard guard = clazz.getAnnotation(SWCommand.Guard.class); + if (guard != null) { + if (guard.value() != null) { + return getGuardChecker(guard.value(), localGuardChecker); + } + return getGuardChecker(clazz.getTypeName(), localGuardChecker); + } + return null; + } + + private static GuardChecker getGuardChecker(String s, Map localGuardChecker) { + GuardChecker guardChecker = localGuardChecker.getOrDefault(s, GUARD_FUNCTIONS.getOrDefault(s, null)); + if (guardChecker == null) { + throw new IllegalArgumentException("No guard found for " + s); + } + return guardChecker; + } + 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; @@ -166,6 +245,25 @@ public class SWCommandUtils { }; } + public static TypeMapper> createEnumMapper(Class> enumClass) { + Enum[] enums = enumClass.getEnumConstants(); + List strings = Arrays.stream(enums).map(Enum::name).collect(Collectors.toList()); + return new TypeMapper>() { + @Override + public Enum map(CommandSender commandSender, String[] previousArguments, String s) { + for (Enum e : enums) { + if (e.name().equalsIgnoreCase(s)) return e; + } + return null; + } + + @Override + public List tabCompletes(CommandSender commandSender, String[] previousArguments, String s) { + return strings; + } + }; + } + private static Function numberMapper(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 07f05d8..3cbc445 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -19,18 +19,16 @@ package de.steamwar.command; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.function.Function; import java.util.function.Predicate; -import java.util.logging.Level; - -import static de.steamwar.command.SWCommandUtils.*; class SubCommand { @@ -38,145 +36,62 @@ class SubCommand { Method method; String[] description; String[] subCommand; - TypeMapper[] arguments; - GuardChecker[] guards; private Predicate commandSenderPredicate; private Function commandSenderFunction; GuardChecker guardChecker; - Class varArgType = null; - private boolean help; boolean noTabComplete; + int comparableValue; + + private CommandPart commandPart; SubCommand(SWCommand swCommand, Method method, String[] subCommand, Map> localTypeMapper, Map localGuardChecker, boolean help, String[] description, boolean noTabComplete) { this.swCommand = swCommand; this.method = method; - this.help = help; this.description = description; this.noTabComplete = noTabComplete; + this.subCommand = subCommand; Parameter[] parameters = method.getParameters(); + comparableValue = parameters[parameters.length - 1].isVarArgs() ? Integer.MAX_VALUE : subCommand.length; + + guardChecker = SWCommandUtils.getGuardChecker(parameters[0], localGuardChecker); + + commandPart = SWCommandUtils.generateCommandPart(help, subCommand, parameters, localTypeMapper, localGuardChecker); 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(); - if (parameter.isVarArgs()) { - clazz = clazz.getComponentType(); - varArgType = clazz; - } - - SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); - SWCommand.ClassMapper classMapper = parameter.getAnnotation(SWCommand.ClassMapper.class); - if (clazz.isEnum() && mapper == null && classMapper == null && !MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) { - Class> enumClass = (Class>) clazz; - List tabCompletes = new ArrayList<>(); - for (Enum enumConstant : enumClass.getEnumConstants()) { - tabCompletes.add(enumConstant.name().toLowerCase()); - } - arguments[i - 1] = SWCommandUtils.createMapper(s -> ENUM_MAPPER.apply(enumClass, s), s -> tabCompletes); - continue; - } - - String name = clazz.getTypeName(); - if (classMapper != null) { - name = classMapper.value().getTypeName(); - } else if (mapper != null) { - name = mapper.value(); - } else { - SWCommand.StaticValue staticValue = parameter.getAnnotation(SWCommand.StaticValue.class); - if (staticValue != null && parameter.getType() == String.class) { - arguments[i - 1] = SWCommandUtils.createMapper(staticValue.value()); - guards[i - 1] = getGuardChecker(parameter, localGuardChecker); - continue; - } - } - 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.ClassGuard classGuard = parameter.getAnnotation(SWCommand.ClassGuard.class); - if (classGuard != null) { - if (classGuard.value() == null) { - String s = parameter.getType().getTypeName(); - if (parameter.isVarArgs()) { - s = parameter.getType().getComponentType().getTypeName(); - } - return localGuardChecker.getOrDefault(s, GUARD_FUNCTIONS.getOrDefault(s, null)); - } - GuardChecker current = localGuardChecker.getOrDefault(classGuard.value().getTypeName(), GUARD_FUNCTIONS.getOrDefault(classGuard.value().getTypeName(), null)); - if (current == null) { - Bukkit.getLogger().log(Level.WARNING, () -> "The guard checker with name '" + classGuard.value().getTypeName() + "' is neither a local guard checker nor a global one"); - } - return current; - } - SWCommand.Guard guard = parameter.getAnnotation(SWCommand.Guard.class); - if (guard != null) { - if (guard.value() == null || guard.value().isEmpty()) { - String s = parameter.getType().getTypeName(); - if (parameter.isVarArgs()) { - s = parameter.getType().getComponentType().getTypeName(); - } - return localGuardChecker.getOrDefault(s, GUARD_FUNCTIONS.getOrDefault(s, null)); - } - GuardChecker current = localGuardChecker.getOrDefault(guard.value(), GUARD_FUNCTIONS.getOrDefault(guard.value(), null)); - if (current == 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; - } - if (varArgType == null && args.length > arguments.length + subCommand.length) { - return false; - } try { if (!commandSenderPredicate.test(commandSender)) { return false; } - Object[] objects = SWCommandUtils.generateArgumentArray(commandSender, arguments, guards, args, varArgType, subCommand); - objects[0] = commandSenderFunction.apply(commandSender); - for (int i = subCommand.length; i < args.length; i++) { - GuardChecker current; - if (i == subCommand.length) { - current = guardChecker; - } else { - if (i >= objects.length + subCommand.length) { - current = guards[guards.length - 1]; - } else { - current = guards[i - 1 - subCommand.length]; - } + + if (commandPart == null) { + if (args.length != 0) { + return false; } - if (current != null) { - GuardResult guardResult; - if (i == 0) { - guardResult = current.guard(commandSender, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, new String[0], null); - } else { - guardResult = current.guard(commandSender, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND, Arrays.copyOf(args, i - 1), args[i - 1]); - } - if (guardResult != GuardResult.ALLOWED) { - if (guardResult == GuardResult.DENIED) { + method.setAccessible(true); + method.invoke(swCommand, commandSenderFunction.apply(commandSender)); + } else { + List objects = new ArrayList<>(); + commandPart.generateArgumentArray(objects, commandSender, args, 0); + if (guardChecker != null) { + GuardResult guardResult = guardChecker.guard(commandSender, GuardCheckType.COMMAND, new String[0], null); + switch (guardResult) { + case ALLOWED: + break; + case DENIED: throw new CommandNoHelpException(); - } - return false; + case DENIED_WITH_HELP: + default: + return true; } } + commandPart.guardCheck(commandSender, args, 0); + method.setAccessible(true); + method.invoke(swCommand, objects); } - method.setAccessible(true); - method.invoke(swCommand, objects); } catch (CommandNoHelpException e) { throw e; } catch (CommandParseException e) { @@ -188,64 +103,14 @@ class SubCommand { } List tabComplete(CommandSender commandSender, String[] args) { - if (varArgType == null && args.length > arguments.length + subCommand.length) { - return null; - } if (guardChecker != null && guardChecker.guard(commandSender, GuardCheckType.TAB_COMPLETE, new String[0], null) != GuardResult.ALLOWED) { return null; } - int index = 0; - 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.equalsIgnoreCase(s)) return null; - index++; + if (commandPart == null) { + return null; } - int guardIndex = 0; - for (TypeMapper argument : arguments) { - String s = argsList.remove(0); - if (argsList.isEmpty()) { - 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[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) { - return null; - } - } catch (Exception e) { - return null; - } - index++; - guardIndex++; - } - if (varArgType != null && !argsList.isEmpty()) { - while (!argsList.isEmpty()) { - String s = argsList.remove(0); - if (argsList.isEmpty()) { - 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, 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) { - return null; - } - } catch (Exception e) { - return null; - } - index++; - } - } - return null; + List list = new ArrayList<>(); + commandPart.generateTabComplete(list, commandSender, args, 0); + return list; } } diff --git a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java index f8ba72a..daa72fd 100644 --- a/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java +++ b/SpigotCore_Main/testsrc/de/steamwar/command/SimpleCommandTest.java @@ -54,6 +54,7 @@ public class SimpleCommandTest { try { simpleCommand.execute(new TestCommandSender(), "", new String[]{"unknown"}); } catch (SecurityException securityException) { + securityException.printStackTrace(); assert false; } } From 5f7f7673f048adfa8860cef8f78339c2c4994853 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 21:37:17 +0100 Subject: [PATCH 17/27] Add BauweltMember TypeMapper --- .../de/steamwar/command/SWCommandUtils.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index fa6c3f3..7de8407 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -19,6 +19,7 @@ package de.steamwar.command; +import de.steamwar.sql.BauweltMember; import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SteamwarUser; import org.bukkit.Bukkit; @@ -78,6 +79,32 @@ public class SWCommandUtils { return SchematicNode.getNodeTabcomplete(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); } }); + MAPPER_FUNCTIONS.put(BauweltMember.class.getTypeName(), new TypeMapper() { + @Override + public BauweltMember map(CommandSender commandSender, String[] previousArguments, String s) { + if (!(commandSender instanceof Player)) { + return null; + } + Player player = (Player) commandSender; + return BauweltMember.getMembers(player.getUniqueId()) + .stream() + .filter(member -> SteamwarUser.get(member.getMemberID()).getUserName().equalsIgnoreCase(s)) + .findAny() + .orElse(null); + } + + @Override + public List tabCompletes(CommandSender commandSender, String[] previousArguments, String s) { + if (!(commandSender instanceof Player)) { + return new ArrayList<>(); + } + Player player = (Player) commandSender; + return BauweltMember.getMembers(player.getUniqueId()) + .stream() + .map(m -> SteamwarUser.get(m.getMemberID()).getUserName()) + .collect(Collectors.toList()); + } + }); } private static void addMapper(Class clazz, Class alternativeClazz, TypeMapper mapper) { From 563801b0a1bcfc66326f6ea67515f05e25977707 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 21:51:06 +0100 Subject: [PATCH 18/27] Fix SubCommand --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 3cbc445..7eade15 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -89,8 +89,9 @@ class SubCommand { } } commandPart.guardCheck(commandSender, args, 0); + objects.add(0, commandSenderFunction.apply(commandSender)); method.setAccessible(true); - method.invoke(swCommand, objects); + method.invoke(swCommand, objects.toArray()); } } catch (CommandNoHelpException e) { throw e; From 2f331e169aa627c6c119b704163f1fd5141ae1af Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 22:02:15 +0100 Subject: [PATCH 19/27] Fix SubCommand --- SpigotCore_Main/src/de/steamwar/command/SubCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 7eade15..4b66771 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -89,6 +89,7 @@ class SubCommand { } } commandPart.guardCheck(commandSender, args, 0); + for (int i = 0; i < subCommand.length; i++) objects.remove(0); objects.add(0, commandSenderFunction.apply(commandSender)); method.setAccessible(true); method.invoke(swCommand, objects.toArray()); From 86ce3982246af98ee09199b1fc972b05ee21a0fc Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 22:52:30 +0100 Subject: [PATCH 20/27] Fix SubCommand --- .../src/de/steamwar/command/CommandPart.java | 14 ++++++++++++-- .../src/de/steamwar/command/SWCommandUtils.java | 10 +++++++++- .../src/de/steamwar/command/SubCommand.java | 1 - 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index e6dbf8c..666d516 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -20,12 +20,15 @@ package de.steamwar.command; import lombok.AllArgsConstructor; +import lombok.Setter; +import lombok.ToString; import org.bukkit.command.CommandSender; import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; +@ToString public class CommandPart { private static final String[] EMPTY_ARRAY = new String[0]; @@ -43,6 +46,9 @@ public class CommandPart { private CommandPart next = null; + @Setter + private boolean ignoreAsArgument = false; + public CommandPart(TypeMapper typeMapper, GuardChecker guard, Class varArgType, String optional, GuardCheckType guardCheckType) { this.typeMapper = typeMapper; this.guard = guard; @@ -100,13 +106,17 @@ public class CommandPart { throw new CommandParseException(); } if (!validArgument.success) { - current.add(typeMapper.map(commandSender, EMPTY_ARRAY, optional)); + if (!ignoreAsArgument) { + current.add(typeMapper.map(commandSender, EMPTY_ARRAY, optional)); + } if (next != null) { next.generateArgumentArray(current, commandSender, args, startIndex); } return; } - current.add(validArgument.value); + if (!ignoreAsArgument) { + current.add(validArgument.value); + } if (next != null) { next.generateArgumentArray(current, commandSender, args, startIndex + 1); } diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 7de8407..8e43884 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -113,13 +113,18 @@ public class SWCommandUtils { } static CommandPart generateCommandPart(boolean help, String[] subCommand, Parameter[] parameters, Map> localTypeMapper, Map localGuardChecker) { + CommandPart first = null; CommandPart current = null; for (String s : subCommand) { CommandPart commandPart = new CommandPart(createMapper(s), null, null, null, help ? GuardCheckType.HELP_COMMAND : GuardCheckType.COMMAND); + commandPart.setIgnoreAsArgument(true); if (current != null) { current.setNext(commandPart); } current = commandPart; + if (first == null) { + first = current; + } } for (int i = 1; i < parameters.length; i++) { Parameter parameter = parameters[i]; @@ -133,8 +138,11 @@ public class SWCommandUtils { current.setNext(commandPart); } current = commandPart; + if (first == null) { + first = current; + } } - return current; + return first; } static TypeMapper getTypeMapper(Parameter parameter, Map> localTypeMapper) { diff --git a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java index 4b66771..7eade15 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SubCommand.java +++ b/SpigotCore_Main/src/de/steamwar/command/SubCommand.java @@ -89,7 +89,6 @@ class SubCommand { } } commandPart.guardCheck(commandSender, args, 0); - for (int i = 0; i < subCommand.length; i++) objects.remove(0); objects.add(0, commandSenderFunction.apply(commandSender)); method.setAccessible(true); method.invoke(swCommand, objects.toArray()); From 64c8d910c170a71903e50039634ecfe9bae97753 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 23:18:32 +0100 Subject: [PATCH 21/27] Fix SWCommandUtils.generateCommandPart --- .../de/steamwar/command/SWCommandUtils.java | 42 ++----------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index 8e43884..c9b7f43 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -151,8 +151,8 @@ public class SWCommandUtils { clazz = clazz.getComponentType(); } - SWCommand.ClassMapper classMapper = clazz.getAnnotation(SWCommand.ClassMapper.class); - SWCommand.Mapper mapper = clazz.getAnnotation(SWCommand.Mapper.class); + SWCommand.ClassMapper classMapper = parameter.getAnnotation(SWCommand.ClassMapper.class); + SWCommand.Mapper mapper = parameter.getAnnotation(SWCommand.Mapper.class); if (clazz.isEnum() && classMapper == null && mapper == null && !MAPPER_FUNCTIONS.containsKey(clazz.getTypeName()) && !localTypeMapper.containsKey(clazz.getTypeName())) { return createEnumMapper((Class>) clazz); } @@ -181,7 +181,7 @@ public class SWCommandUtils { clazz = clazz.getComponentType(); } - SWCommand.ClassGuard classGuard = clazz.getAnnotation(SWCommand.ClassGuard.class); + SWCommand.ClassGuard classGuard = parameter.getAnnotation(SWCommand.ClassGuard.class); if (classGuard != null) { if (classGuard.value() != null) { return getGuardChecker(classGuard.value().getTypeName(), localGuardChecker); @@ -189,7 +189,7 @@ public class SWCommandUtils { return getGuardChecker(clazz.getTypeName(), localGuardChecker); } - SWCommand.Guard guard = clazz.getAnnotation(SWCommand.Guard.class); + SWCommand.Guard guard = parameter.getAnnotation(SWCommand.Guard.class); if (guard != null) { if (guard.value() != null) { return getGuardChecker(guard.value(), localGuardChecker); @@ -207,40 +207,6 @@ public class SWCommandUtils { return guardChecker; } - 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) { - if (!args[index].equalsIgnoreCase(subCommand[index])) throw new CommandParseException(); - index++; - } - - int length = 0; - if (varArgType != null) { - length = args.length - parameters.length - subCommand.length + 1; - arguments[arguments.length - 1] = Array.newInstance(varArgType, length); - if (index > args.length - 1) return arguments; - } - - for (int i = 0; i < parameters.length - (varArgType != null ? 1 : 0); i++) { - arguments[i + 1] = parameters[i].map(commandSender, Arrays.copyOf(args, index), args[index]); - index++; - if (arguments[i + 1] == null) throw new CommandParseException(); - } - - if (varArgType != null) { - Object varArgument = arguments[arguments.length - 1]; - - for (int i = 0; i < length; i++) { - 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); - index++; - } - } - return arguments; - } - public static void addMapper(Class clazz, TypeMapper mapper) { addMapper(clazz.getTypeName(), mapper); } From 006754990c7c05b2f33d37df24d2900f63d1474d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 23:23:41 +0100 Subject: [PATCH 22/27] Fix SWCommandUtils.generateCommandPart --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index c9b7f43..b212b00 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -191,7 +191,7 @@ public class SWCommandUtils { SWCommand.Guard guard = parameter.getAnnotation(SWCommand.Guard.class); if (guard != null) { - if (guard.value() != null) { + if (guard.value() != null && !guard.value().isEmpty()) { return getGuardChecker(guard.value(), localGuardChecker); } return getGuardChecker(clazz.getTypeName(), localGuardChecker); @@ -200,6 +200,9 @@ public class SWCommandUtils { } private static GuardChecker getGuardChecker(String s, Map localGuardChecker) { + System.out.println(": " + s); + System.out.println(localGuardChecker); + System.out.println(GUARD_FUNCTIONS); GuardChecker guardChecker = localGuardChecker.getOrDefault(s, GUARD_FUNCTIONS.getOrDefault(s, null)); if (guardChecker == null) { throw new IllegalArgumentException("No guard found for " + s); From 46beaddbd729756e8ef5641d7bc669ec5768a3af Mon Sep 17 00:00:00 2001 From: yoyosource Date: Thu, 9 Dec 2021 23:24:06 +0100 Subject: [PATCH 23/27] Fix SWCommandUtils.generateCommandPart --- SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index b212b00..ca20cf3 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -28,7 +28,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.lang.annotation.Annotation; -import java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; @@ -200,9 +199,6 @@ public class SWCommandUtils { } private static GuardChecker getGuardChecker(String s, Map localGuardChecker) { - System.out.println(": " + s); - System.out.println(localGuardChecker); - System.out.println(GUARD_FUNCTIONS); GuardChecker guardChecker = localGuardChecker.getOrDefault(s, GUARD_FUNCTIONS.getOrDefault(s, null)); if (guardChecker == null) { throw new IllegalArgumentException("No guard found for " + s); From 7e96e4c2d5d30ea7688fbab672e76ff95a9aa6d4 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 10 Dec 2021 11:11:30 +0100 Subject: [PATCH 24/27] Fix CommandPart.generateArgumentArray for vararg --- SpigotCore_Main/src/de/steamwar/command/CommandPart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java index 666d516..e150052 100644 --- a/SpigotCore_Main/src/de/steamwar/command/CommandPart.java +++ b/SpigotCore_Main/src/de/steamwar/command/CommandPart.java @@ -84,7 +84,7 @@ public class CommandPart { } public void generateArgumentArray(List current, CommandSender commandSender, String[] args, int startIndex) { - if (startIndex >= args.length) { + if (startIndex >= args.length && varArgType == null) { throw new CommandParseException(); } From afa80082b3b394801fd52e9fcbd8a0fd8be6aff3 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 10 Dec 2021 18:14:06 +0100 Subject: [PATCH 25/27] Fix SWCommandUtils.createEnumMapper --- 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 ca20cf3..cdcd346 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -247,7 +247,7 @@ public class SWCommandUtils { public static TypeMapper> createEnumMapper(Class> enumClass) { Enum[] enums = enumClass.getEnumConstants(); - List strings = Arrays.stream(enums).map(Enum::name).collect(Collectors.toList()); + List strings = Arrays.stream(enums).map(Enum::name).map(String::toLowerCase).collect(Collectors.toList()); return new TypeMapper>() { @Override public Enum map(CommandSender commandSender, String[] previousArguments, String s) { From c1b3ab6dbbf14c2deecfdb753eeb1ed68fba8306 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 11 Dec 2021 13:43:16 +0100 Subject: [PATCH 26/27] Fix SWCommandUtils SteamwarUser --- .../de/steamwar/command/SWCommandUtils.java | 8 +------ .../src/de/steamwar/sql/SteamwarUser.java | 24 ------------------- SpigotCore_Main/testsrc/.gitkeep | 0 3 files changed, 1 insertion(+), 31 deletions(-) delete mode 100644 SpigotCore_Main/testsrc/.gitkeep diff --git a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java index cdcd346..7438ac1 100644 --- a/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/SWCommandUtils.java @@ -60,13 +60,7 @@ public class SWCommandUtils { if (s.equals("a") || s.equals("adventure") || s.equals("2")) return GameMode.ADVENTURE; return null; }, s -> Arrays.asList("s", "survival", "0", "c", "creative", "1", "sp", "spectator", "3", "a", "adventure", "2"))); - MAPPER_FUNCTIONS.put(SteamwarUser.class.getTypeName(), createMapper(SteamwarUser::get, s -> { - if (s.length() < 1) { - return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - } - List steamwarUsers = SteamwarUser.getByPrefix(s); - return steamwarUsers.stream().map(SteamwarUser::getUserName).limit(40).collect(Collectors.toList()); - })); + MAPPER_FUNCTIONS.put(SteamwarUser.class.getTypeName(), createMapper(SteamwarUser::get, s -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()))); MAPPER_FUNCTIONS.put(SchematicNode.class.getTypeName(), new TypeMapper() { @Override public SchematicNode map(CommandSender commandSender, String[] previousArguments, String s) { diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index 9188cb7..bbad8d7 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -33,19 +33,16 @@ public class SteamwarUser { private static final SQL.Statement getId = new SQL.Statement("SELECT * FROM UserData WHERE id = ?"); private static final SQL.Statement getUUID = new SQL.Statement("SELECT * FROM UserData WHERE UUID = ?"); private static final SQL.Statement getName = new SQL.Statement("SELECT * FROM UserData WHERE lower(UserName) = ?"); - private static final SQL.Statement startWithName = new SQL.Statement("SELECT * FROM UserData WHERE lower(UserName) LIKE ?"); private static final Map byUUID = new HashMap<>(); private static final Map byName = new HashMap<>(); private static final Map byId = new HashMap<>(); - private static final Map> byPrefix = new HashMap<>(); static{ Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { byId.clear(); byName.clear(); byUUID.clear(); - byPrefix.clear(); }, 72000, 72000); } @@ -97,27 +94,6 @@ public class SteamwarUser { return bedrock; } - public static List getByPrefix(String userName){ - if (userName.isEmpty()) { - return new ArrayList<>(); - } - List users = byPrefix.get(userName.toLowerCase().substring(0, 1)); - if (users == null) { - users = startWithName.select(rs -> { - List steamwarUsers = new ArrayList<>(); - while (rs.next()) { - String name = rs.getString("UserName"); - SteamwarUser user = byName.get(name.toLowerCase()); - if (user == null) user = new SteamwarUser(rs); - steamwarUsers.add(user); - } - return steamwarUsers; - }, userName.toLowerCase() + "%"); - byPrefix.put(userName.toLowerCase().substring(0, 1), users); - } - return users.stream().filter(user -> user.getUserName().toLowerCase().startsWith(userName.toLowerCase())).collect(Collectors.toList()); - } - public static SteamwarUser get(String userName){ SteamwarUser user = byName.get(userName.toLowerCase()); if(user == null) diff --git a/SpigotCore_Main/testsrc/.gitkeep b/SpigotCore_Main/testsrc/.gitkeep deleted file mode 100644 index e69de29..0000000 From 1fe04962a568c2abcc1018dea1462f8db1d4164a Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 11 Dec 2021 13:59:53 +0100 Subject: [PATCH 27/27] Fix SWCommandUtils SteamwarUser --- SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java index bbad8d7..115367f 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SteamwarUser.java @@ -25,8 +25,9 @@ import org.bukkit.entity.Player; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; -import java.util.stream.Collectors; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; public class SteamwarUser {