From e7c59b206242462a4d9938d4b4d953c16092aa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 13 Sep 2020 22:07:34 +0200 Subject: [PATCH] Fix suggestions and add a bukkit test module --- .../commands/CommandManager.java | 3 + .../commands/CommandTree.java | 19 ++--- .../components/standard/StringComponent.java | 40 ++++++++-- cloud-minecraft/cloud-bukkit-test/pom.xml | 75 +++++++++++++++++++ .../commands/BukkitTest.java | 74 ++++++++++++++++++ .../commands/package-info.java | 28 +++++++ .../src/main/resources/plugin.yml | 5 ++ .../commands/BukkitCommand.java | 10 ++- .../BukkitPluginRegistrationHandler.java | 18 +++-- pom.xml | 2 + 10 files changed, 248 insertions(+), 26 deletions(-) create mode 100644 cloud-minecraft/cloud-bukkit-test/pom.xml create mode 100644 cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java create mode 100644 cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/package-info.java create mode 100644 cloud-minecraft/cloud-bukkit-test/src/main/resources/plugin.yml diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java index 4b21a1d8..af0fac9d 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -141,6 +141,9 @@ public abstract class CommandManager { final Node> child = children.get(0); if (child.getValue() != null) { if (commandQueue.isEmpty()) { - if (child.isLeaf()) { - /* Child is leaf, and so no suggestions should be sent */ - return Collections.emptyList(); - } else { - /* Send all suggestions */ - return child.getValue().getParser().suggestions(commandContext, ""); - } + return child.getValue().getParser().suggestions(commandContext, ""); + } else if (child.isLeaf() && commandQueue.size() < 2) { + return child.getValue().getParser().suggestions(commandContext, commandQueue.peek()); + } else if (child.isLeaf()) { + return Collections.emptyList(); } final ComponentParseResult result = child.getValue().getParser().parse(commandContext, commandQueue); if (result.getParsedValue().isPresent()) { - if (child.isLeaf()) { - /* Child is leaf, and so no suggestions should be sent */ - return Collections.emptyList(); - } commandContext.store(child.getValue().getName(), result.getParsedValue().get()); return this.getSuggestions(commandContext, commandQueue, child); } else if (result.getFailure().isPresent()) { - /* I need to return ze error */ - return Collections.emptyList(); + return child.getValue().getParser().suggestions(commandContext, commandQueue.peek()); } } } diff --git a/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/StringComponent.java b/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/StringComponent.java index 93a73040..f65855e6 100644 --- a/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/StringComponent.java +++ b/cloud-core/src/main/java/com/intellectualsites/commands/components/standard/StringComponent.java @@ -30,17 +30,23 @@ import com.intellectualsites.commands.context.CommandContext; import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; import java.util.Queue; import java.util.StringJoiner; +import java.util.function.BiFunction; @SuppressWarnings("unused") public final class StringComponent extends CommandComponent { private final StringMode stringMode; - private StringComponent(final boolean required, @Nonnull final String name, - @Nonnull final StringMode stringMode, @Nonnull final String defaultValue) { - super(required, name, new StringParser<>(stringMode), defaultValue); + private StringComponent(final boolean required, + @Nonnull final String name, + @Nonnull final StringMode stringMode, + @Nonnull final String defaultValue, + @Nonnull final BiFunction, String, List> suggestionsProvider) { + super(required, name, new StringParser<>(stringMode, suggestionsProvider), defaultValue); this.stringMode = stringMode; } @@ -115,6 +121,7 @@ public final class StringComponent extends CommandCompo public static final class Builder extends CommandComponent.Builder { private StringMode stringMode = StringMode.SINGLE; + private BiFunction, String, List> suggestionsProvider = (v1, v2) -> Collections.emptyList(); protected Builder(@Nonnull final String name) { super(name); @@ -153,6 +160,19 @@ public final class StringComponent extends CommandCompo return this; } + /** + * Set the suggestions provider + * + * @param suggestionsProvider Suggestions provider + * @return Builder instance + */ + @Nonnull + public Builder withSuggestionsProvider(@Nonnull final BiFunction, + String, List> suggestionsProvider) { + this.suggestionsProvider = suggestionsProvider; + return this; + } + /** * Builder a new string component * @@ -161,7 +181,8 @@ public final class StringComponent extends CommandCompo @Nonnull @Override public StringComponent build() { - return new StringComponent<>(this.isRequired(), this.getName(), this.stringMode, this.getDefaultValue()); + return new StringComponent<>(this.isRequired(), this.getName(), this.stringMode, + this.getDefaultValue(), this.suggestionsProvider); } } @@ -170,9 +191,12 @@ public final class StringComponent extends CommandCompo private static final class StringParser implements ComponentParser { private final StringMode stringMode; + private final BiFunction, String, List> suggestionsProvider; - private StringParser(@Nonnull final StringMode stringMode) { + private StringParser(@Nonnull final StringMode stringMode, + @Nonnull final BiFunction, String, List> suggestionsProvider) { this.stringMode = stringMode; + this.suggestionsProvider = suggestionsProvider; } @Nonnull @@ -228,6 +252,12 @@ public final class StringComponent extends CommandCompo return ComponentParseResult.success(sj.toString()); } + + @Nonnull + @Override + public List suggestions(@Nonnull final CommandContext commandContext, @Nonnull final String input) { + return this.suggestionsProvider.apply(commandContext, input); + } } diff --git a/cloud-minecraft/cloud-bukkit-test/pom.xml b/cloud-minecraft/cloud-bukkit-test/pom.xml new file mode 100644 index 00000000..51adcac3 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit-test/pom.xml @@ -0,0 +1,75 @@ + + + + + + cloud + com.intellectualsites + 1.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + cloud-bukkit-test + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + false + + + + + + + + + + com.intellectualsites + cloud-bukkit + 1.0-SNAPSHOT + + + org.bukkit + bukkit + 1.8.8-R0.1-SNAPSHOT + provided + + + diff --git a/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java new file mode 100644 index 00000000..33734310 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/BukkitTest.java @@ -0,0 +1,74 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package com.intellectualsites.commands; + +import com.intellectualsites.commands.components.StaticComponent; +import com.intellectualsites.commands.components.standard.EnumComponent; +import com.intellectualsites.commands.components.standard.StringComponent; +import com.intellectualsites.commands.execution.CommandExecutionCoordinator; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public final class BukkitTest extends JavaPlugin { + + @Override + public void onLoad() { + try { + final BukkitCommandManager commandManager = new BukkitCommandManager(this, + CommandExecutionCoordinator.simpleCoordinator()); + commandManager.registerCommand(commandManager.commandBuilder("gamemode", + Collections.singleton("gajmöde"), + BukkitCommandMetaBuilder.builder() + .withDescription("Your ugli") + .build()) + .withComponent(EnumComponent.required(GameMode.class, "gamemode")) + .withComponent(StringComponent.newBuilder("player") + .withSuggestionsProvider((v1, v2) -> { + final List suggestions = new ArrayList<>(Bukkit.getOnlinePlayers().stream() + .map(Player::getName).collect(Collectors.toList())); + suggestions.add("dog"); + suggestions.add("cat"); + return suggestions; + }).build()) + .withHandler(c -> c.getCommandSender() + .asPlayer() + .setGameMode(c.get("gamemode") + .orElse(GameMode.SURVIVAL))) + .build()) + .registerCommand(commandManager.commandBuilder("kenny") + .withComponent(StaticComponent.required("sux")) + .build()); + } catch (final Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/package-info.java b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/package-info.java new file mode 100644 index 00000000..316be661 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit-test/src/main/java/com/intellectualsites/commands/package-info.java @@ -0,0 +1,28 @@ +// +// MIT License +// +// Copyright (c) 2020 Alexander Söderberg +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +/** + * Stuff + */ +package com.intellectualsites.commands; diff --git a/cloud-minecraft/cloud-bukkit-test/src/main/resources/plugin.yml b/cloud-minecraft/cloud-bukkit-test/src/main/resources/plugin.yml new file mode 100644 index 00000000..ed22e731 --- /dev/null +++ b/cloud-minecraft/cloud-bukkit-test/src/main/resources/plugin.yml @@ -0,0 +1,5 @@ +name: Command-Test +author: Citymonstret +main: com.intellectualsites.commands.BukkitTest +version: 1.0 +api-version: 1.13 diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommand.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommand.java index 6c2c7c6c..1de292be 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommand.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitCommand.java @@ -35,12 +35,15 @@ final class BukkitCommand extends org.bukkit.command.Command implements PluginId private final CommandComponent command; private final BukkitCommandManager bukkitCommandManager; + private final com.intellectualsites.commands.Command cloudCommand; - BukkitCommand(@Nonnull final CommandComponent command, + BukkitCommand(@Nonnull final com.intellectualsites.commands.Command cloudCommand, + @Nonnull final CommandComponent command, @Nonnull final BukkitCommandManager bukkitCommandManager) { super(command.getName()); this.command = command; this.bukkitCommandManager = bukkitCommandManager; + this.cloudCommand = cloudCommand; } @Override @@ -62,6 +65,11 @@ final class BukkitCommand extends org.bukkit.command.Command implements PluginId return true; } + @Override + public String getDescription() { + return this.cloudCommand.getCommandMeta().getOrDefault("description", ""); + } + @Override public List tabComplete(final CommandSender sender, final String alias, final String[] args) throws IllegalArgumentException { diff --git a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java index 7519be99..79a8d92d 100644 --- a/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java +++ b/cloud-minecraft/cloud-bukkit/src/main/java/com/intellectualsites/commands/BukkitPluginRegistrationHandler.java @@ -28,6 +28,7 @@ import com.intellectualsites.commands.internal.CommandRegistrationHandler; import org.bukkit.Bukkit; import org.bukkit.command.CommandMap; import org.bukkit.command.SimpleCommandMap; +import org.bukkit.help.GenericCommandHelpTopic; import javax.annotation.Nonnull; import java.lang.reflect.Field; @@ -41,6 +42,7 @@ final class BukkitPluginRegistrationHandler implements CommandRegistrationHandle private Map bukkitCommands; private BukkitCommandManager bukkitCommandManager; + private CommandMap commandMap; BukkitPluginRegistrationHandler() { } @@ -48,14 +50,14 @@ final class BukkitPluginRegistrationHandler implements CommandRegistrationHandle void initialize(@Nonnull final BukkitCommandManager bukkitCommandManager) throws Exception { final Method getCommandMap = Bukkit.getServer().getClass().getDeclaredMethod("getCommandMap"); getCommandMap.setAccessible(true); - final CommandMap commandMap = (CommandMap) getCommandMap.invoke(Bukkit.getServer()); + this.commandMap = (CommandMap) getCommandMap.invoke(Bukkit.getServer()); final Field knownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands"); knownCommands.setAccessible(true); - @SuppressWarnings("ALL") - final Map bukkitCommands = + @SuppressWarnings("ALL") final Map bukkitCommands = (Map) knownCommands.get(commandMap); this.bukkitCommands = bukkitCommands; this.bukkitCommandManager = bukkitCommandManager; + Bukkit.getHelpMap().registerHelpTopicFactory(BukkitCommand.class, GenericCommandHelpTopic::new); } @Override @@ -71,11 +73,13 @@ final class BukkitPluginRegistrationHandler implements CommandRegistrationHandle } else { label = commandComponent.getName(); } - @SuppressWarnings("unchecked") - final BukkitCommand bukkitCommand = new BukkitCommand((CommandComponent) commandComponent, - this.bukkitCommandManager); - this.bukkitCommands.put(label, bukkitCommand); + @SuppressWarnings("unchecked") final BukkitCommand bukkitCommand = new BukkitCommand( + (Command) command, + (CommandComponent) commandComponent, + this.bukkitCommandManager); this.registeredCommands.put(commandComponent, bukkitCommand); + this.commandMap.register(commandComponent.getName(), this.bukkitCommandManager.getOwningPlugin().getName().toLowerCase(), + bukkitCommand); return true; } diff --git a/pom.xml b/pom.xml index 3c1dabf0..51c41d7f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,8 @@ cloud-minecraft/cloud-bukkit cloud-core cloud-pipeline + + cloud-minecraft/cloud-bukkit-test pom 2020