🐛 Fix async completions (#38)

Co-authored-by: Alexander Söderberg <sauilitired@gmail.com>
This commit is contained in:
Jason 2020-10-08 04:12:07 -07:00 committed by GitHub
parent aa572e3533
commit 882154a6a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 160 additions and 54 deletions

View file

@ -39,7 +39,6 @@ import cloud.commandframework.arguments.standard.IntegerArgument;
import cloud.commandframework.arguments.standard.ShortArgument;
import cloud.commandframework.arguments.standard.StringArgument;
import cloud.commandframework.context.CommandContext;
import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext;
import cloud.commandframework.permission.CommandPermission;
import cloud.commandframework.permission.Permission;
import cloud.commandframework.types.tuples.Pair;
@ -62,9 +61,7 @@ import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@ -438,28 +435,23 @@ public final class CloudBrigadierManager<C, S> {
final @NonNull SuggestionsBuilder builder
) {
final CommandContext<C> commandContext = this.dummyContextProvider.get();
final LinkedList<String> inputQueue = new LinkedList<>(Collections.singletonList(builder.getInput()));
final CommandPreprocessingContext<C> commandPreprocessingContext =
new CommandPreprocessingContext<>(commandContext, inputQueue);
/*
List<String> results = server.tabComplete(context.getSource().getBukkitSender(), builder.getInput(),
context.getSource().getWorld(), context.getSource().getPosition(), true);
*/
String command = builder.getInput();
if (command.startsWith("/") /* Minecraft specific */) {
command = command.substring(1);
}
final List<String> suggestions = this.commandManager.suggest(commandContext.getSender(), command);
/*
System.out.println("Filtering out with: " + builder.getInput());
final CommandSuggestionProcessor<C> processor = this.commandManager.getCommandSuggestionProcessor();
final List<String> filteredSuggestions = processor.apply(commandPreprocessingContext, suggestions);
System.out.println("Current suggestions: ");
for (final String suggestion : filteredSuggestions) {
System.out.printf("- %s\n", suggestion);
}*/
/* Remove namespace */
String leading = command.split(" ")[0];
if (leading.contains(":")) {
command = command.substring(leading.split(":")[0].length() + 1);
}
final List<String> suggestions = this.commandManager.suggest(
commandContext.getSender(),
command
);
for (final String suggestion : suggestions) {
String tooltip = argument.getName();
if (!(argument instanceof StaticArgument)) {

View file

@ -144,23 +144,6 @@ final class BukkitCommand<C> extends org.bukkit.command.Command implements Plugi
return this.cloudCommand.getCommandMeta().getOrDefault("description", "");
}
@Override
public List<String> tabComplete(
final @NonNull CommandSender sender,
final @NonNull String alias,
final @NonNull String @NonNull [] args
)
throws IllegalArgumentException {
final StringBuilder builder = new StringBuilder(this.command.getName());
for (final String string : args) {
builder.append(" ").append(string);
}
return this.manager.suggest(
this.manager.getCommandSenderMapper().apply(sender),
builder.toString()
);
}
@Override
public Plugin getPlugin() {
return this.manager.getOwningPlugin();

View file

@ -156,6 +156,12 @@ public class BukkitCommandManager<C> extends CommandManager<C> {
new MultipleEntitySelectorArgument.MultipleEntitySelectorParser<>());
this.getParserRegistry().registerParserSupplier(TypeToken.get(MultiplePlayerSelector.class), parserParameters ->
new MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<>());
/* Register suggestion listener */
this.owningPlugin.getServer().getPluginManager().registerEvents(
new CommandSuggestionsListener<>(this),
this.owningPlugin
);
}
/**
@ -282,6 +288,32 @@ public class BukkitCommandManager<C> extends CommandManager<C> {
}
}
/**
* Strip the plugin namespace from a plugin namespaced command. This
* will also strip the leading '/' if it's present
*
* @param command Command
* @return Stripped command
*/
public final @NonNull String stripNamespace(final @NonNull String command) {
@NonNull String input;
/* Remove leading '/' */
if (command.charAt(0) == '/') {
input = command.substring(1);
} else {
input = command;
}
/* Remove leading plugin namespace */
final String namespace = String.format("%s:", this.getOwningPlugin().getName().toLowerCase());
if (input.startsWith(namespace)) {
input = input.substring(namespace.length());
}
return input;
}
/**
* Get the backwards command sender plugin
*

View file

@ -89,13 +89,16 @@ public class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHa
this.bukkitCommandManager
);
this.registeredCommands.put(commandArgument, bukkitCommand);
if (!this.bukkitCommands.containsKey(label)) {
this.recognizedAliases.add(label);
}
this.recognizedAliases.add(getNamespacedLabel(label));
this.commandMap.register(
label,
this.bukkitCommandManager.getOwningPlugin().getName().toLowerCase(),
bukkitCommand
);
this.registerExternal(label, command, bukkitCommand);
this.recognizedAliases.add(label);
if (this.bukkitCommandManager.getSplitAliases()) {
for (final String alias : aliases) {
@ -107,12 +110,16 @@ public class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHa
(CommandArgument<C, ?>) commandArgument,
this.bukkitCommandManager
);
this.commandMap.register(alias, this.bukkitCommandManager.getOwningPlugin()
.getName().toLowerCase(),
if (!this.bukkitCommands.containsKey(alias)) {
this.recognizedAliases.add(alias);
}
this.recognizedAliases.add(getNamespacedLabel(alias));
this.commandMap.register(
alias,
this.bukkitCommandManager.getOwningPlugin().getName().toLowerCase(),
bukkitCommand
);
this.registerExternal(alias, command, aliasCommand);
this.recognizedAliases.add(alias);
}
}
}
@ -120,6 +127,10 @@ public class BukkitPluginRegistrationHandler<C> implements CommandRegistrationHa
return true;
}
private @NonNull String getNamespacedLabel(final @NonNull String label) {
return String.format("%s:%s", this.bukkitCommandManager.getOwningPlugin().getName(), label).toLowerCase();
}
/**
* Check if the given alias is recognizable by this registration handler
*

View file

@ -0,0 +1,70 @@
//
// MIT License
//
// Copyright (c) 2020 Alexander Söderberg & Contributors
//
// 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 cloud.commandframework.bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.TabCompleteEvent;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.ArrayList;
import java.util.List;
final class CommandSuggestionsListener<C> implements Listener {
private final BukkitCommandManager<C> bukkitCommandManager;
CommandSuggestionsListener(final @NonNull BukkitCommandManager<C> bukkitCommandManager) {
this.bukkitCommandManager = bukkitCommandManager;
}
@EventHandler
void onTabCompletion(final @NonNull TabCompleteEvent event) {
if (event.getBuffer().isEmpty() || !event.getBuffer().startsWith("/")) {
return;
}
@SuppressWarnings("unchecked") final BukkitPluginRegistrationHandler<C> bukkitPluginRegistrationHandler =
(BukkitPluginRegistrationHandler<C>) this.bukkitCommandManager.getCommandRegistrationHandler();
/* Turn '/plugin:command arg1 arg2 ...' into 'plugin:command' */
final String commandLabel = event.getBuffer().substring(1).split(" ")[0];
if (!bukkitPluginRegistrationHandler.isRecognized(commandLabel)) {
return;
}
final CommandSender sender = event.getSender();
final C cloudSender = this.bukkitCommandManager.getCommandSenderMapper().apply(sender);
final String inputBuffer = this.bukkitCommandManager.stripNamespace(event.getBuffer());
final List<String> suggestions = new ArrayList<>(this.bukkitCommandManager.suggest(
cloudSender,
inputBuffer
));
event.setCompletions(suggestions);
}
}

View file

@ -33,9 +33,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.ArrayList;
import java.util.List;
class AsyncCommandSuggestionsListener<C> implements Listener {
private static final long CACHE_EXPIRATION_TIME = 30L;
final class AsyncCommandSuggestionsListener<C> implements Listener {
private final PaperCommandManager<C> paperCommandManager;
@ -44,25 +42,30 @@ class AsyncCommandSuggestionsListener<C> implements Listener {
}
@EventHandler
void onTabCompletion(final @NonNull AsyncTabCompleteEvent event) throws Exception {
void onTabCompletion(final @NonNull AsyncTabCompleteEvent event) {
if (event.getBuffer().isEmpty() || !event.getBuffer().startsWith("/")) {
return;
}
final String[] arguments = event.getBuffer().substring(1).split(" ");
if (this.paperCommandManager.getCommandTree().getNamedNode(arguments[0]) == null) {
return;
}
@SuppressWarnings("unchecked") final BukkitPluginRegistrationHandler<C> bukkitPluginRegistrationHandler =
@SuppressWarnings("unchecked")
final BukkitPluginRegistrationHandler<C> bukkitPluginRegistrationHandler =
(BukkitPluginRegistrationHandler<C>) this.paperCommandManager.getCommandRegistrationHandler();
if (!bukkitPluginRegistrationHandler.isRecognized(arguments[0])) {
/* Turn '/plugin:command arg1 arg2 ...' into 'plugin:command' */
final String commandLabel = event.getBuffer().substring(1).split(" ")[0];
if (!bukkitPluginRegistrationHandler.isRecognized(commandLabel)) {
return;
}
final CommandSender sender = event.getSender();
final C cloudSender = this.paperCommandManager.getCommandSenderMapper().apply(sender);
final String inputBuffer = this.paperCommandManager.stripNamespace(event.getBuffer());
final List<String> suggestions = new ArrayList<>(this.paperCommandManager.suggest(
cloudSender,
event.getBuffer().substring(1)
inputBuffer
));
event.setCompletions(suggestions);
event.setHandled(true);
}