From 6f0fde47b02bffd2c2bea0bbd17f1bb6feca3ae6 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 17:22:49 -0700 Subject: [PATCH] Restored tab completion of player names. Fixes WORLDEDIT-3144. --- .../bukkit/BukkitServerInterface.java | 14 +++- .../sk89q/worldedit/forge/ForgePlatform.java | 24 ++++++- .../extension/platform/CommandManager.java | 2 + .../extension/platform/MultiUserPlatform.java | 36 ++++++++++ .../command/UserCommandCompleter.java | 72 +++++++++++++++++++ .../util/command/CommandCallable.java | 14 +--- .../util/command/CommandCompleter.java | 42 +++++++++++ .../worldedit/util/command/NullCompleter.java | 38 ++++++++++ .../command/parametric/ParametricBuilder.java | 25 +++++++ .../parametric/ParametricCallable.java | 5 +- 10 files changed, 253 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java create mode 100644 src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java create mode 100644 src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java create mode 100644 src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index f67d2372d..1bf4c6a61 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -26,7 +26,9 @@ import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.ServerInterface; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Description; @@ -39,11 +41,12 @@ import org.bukkit.entity.EntityType; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.EnumMap; import java.util.List; import java.util.Map; -public class BukkitServerInterface extends ServerInterface { +public class BukkitServerInterface extends ServerInterface implements MultiUserPlatform { public Server server; public WorldEditPlugin plugin; private CommandRegistration dynamicCommands; @@ -179,4 +182,13 @@ public class BukkitServerInterface extends ServerInterface { public void unregisterCommands() { dynamicCommands.unregisterCommands(); } + + @Override + public Collection getConnectedUsers() { + List users = new ArrayList(); + for (org.bukkit.entity.Player player : Bukkit.getServer().getOnlinePlayers()) { + users.add(new BukkitPlayer(plugin, this, player)); + } + return users; + } } diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java index 9451908ad..62c04afb3 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -23,7 +23,9 @@ import com.sk89q.worldedit.BiomeTypes; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.ServerInterface; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Description; @@ -38,13 +40,19 @@ import net.minecraft.entity.EntityList; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.ServerConfigurationManager; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; import javax.annotation.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; -class ForgePlatform extends ServerInterface { +class ForgePlatform extends ServerInterface implements MultiUserPlatform { private final ForgeWorldEdit mod; private final MinecraftServer server; @@ -213,4 +221,16 @@ class ForgePlatform extends ServerInterface { return capabilities; } + @Override + public Collection getConnectedUsers() { + List users = new ArrayList(); + ServerConfigurationManager scm = server.getConfigurationManager(); + for (String name : scm.getAllUsernames()) { + EntityPlayerMP entity = scm.getPlayerForUsername(name); + if (entity != null) { + users.add(new ForgePlayer(entity)); + } + } + return users; + } } diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 9c71cfe69..466903332 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -33,6 +33,7 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.internal.command.ActorAuthorizer; import com.sk89q.worldedit.internal.command.CommandLoggingHandler; +import com.sk89q.worldedit.internal.command.UserCommandCompleter; import com.sk89q.worldedit.internal.command.WorldEditBinding; import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; import com.sk89q.worldedit.session.request.Request; @@ -93,6 +94,7 @@ public final class CommandManager { // Set up the commands manager ParametricBuilder builder = new ParametricBuilder(); builder.setAuthorizer(new ActorAuthorizer()); + builder.setDefaultCompleter(new UserCommandCompleter(platformManager)); builder.addBinding(new WorldEditBinding(worldEdit)); builder.addExceptionConverter(new WorldEditExceptionConverter(worldEdit)); builder.addInvokeListener(new LegacyCommandsHandler()); diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java b/src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java new file mode 100644 index 000000000..6fa94e017 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java @@ -0,0 +1,36 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.extension.platform; + +import java.util.Collection; + +/** + * Implements a platform with multiple connected users. + */ +public interface MultiUserPlatform extends Platform { + + /** + * Get a list of connected users. + * + * @return a list of connected users + */ + Collection getConnectedUsers(); + +} diff --git a/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java b/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java new file mode 100644 index 000000000..63957cbca --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java @@ -0,0 +1,72 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.internal.command; + +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandLocals; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.MultiUserPlatform; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extension.platform.PlatformManager; +import com.sk89q.worldedit.util.command.CommandCompleter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Provides the names of connected users as suggestions. + */ +public class UserCommandCompleter implements CommandCompleter { + + private final PlatformManager platformManager; + + /** + * Create a new instance. + * + * @param platformManager the platform manager + */ + public UserCommandCompleter(PlatformManager platformManager) { + checkNotNull(platformManager); + this.platformManager = platformManager; + } + + @Override + public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { + Platform platform = platformManager.queryCapability(Capability.USER_COMMANDS); + if (platform instanceof MultiUserPlatform) { + List suggestions = new ArrayList(); + Collection users = ((MultiUserPlatform) platform).getConnectedUsers(); + for (Actor user : users) { + if (user.getName().toLowerCase().startsWith(arguments.toLowerCase().trim())) { + suggestions.add(user.getName()); + } + } + return suggestions; + } else { + return Collections.emptyList(); + } + } + +} diff --git a/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java b/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java index 3c75884c5..85b4133a0 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java +++ b/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java @@ -22,12 +22,10 @@ package com.sk89q.worldedit.util.command; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandLocals; -import java.util.List; - /** * A command that can be executed. */ -public interface CommandCallable { +public interface CommandCallable extends CommandCompleter { /** * Execute the correct command based on the input. @@ -41,16 +39,6 @@ public interface CommandCallable { * @throws CommandException thrown on a command error */ boolean call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException; - - /** - * Get a list of suggestions based on input. - * - * @param arguments the arguments entered up to this point - * @param locals the locals - * @return a list of suggestions - * @throws CommandException thrown if there was a parsing error - */ - List getSuggestions(String arguments, CommandLocals locals) throws CommandException; /** * Get an object describing this command. diff --git a/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java b/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java new file mode 100644 index 000000000..19bf47d60 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java @@ -0,0 +1,42 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.command; + +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandLocals; + +import java.util.List; + +/** + * Provides a method that can provide tab completion for commands. + */ +public interface CommandCompleter { + + /** + * Get a list of suggestions based on input. + * + * @param arguments the arguments entered up to this point + * @param locals the locals + * @return a list of suggestions + * @throws CommandException thrown if there was a parsing error + */ + List getSuggestions(String arguments, CommandLocals locals) throws CommandException; + +} diff --git a/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java b/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java new file mode 100644 index 000000000..10850c696 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java @@ -0,0 +1,38 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.util.command; + +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandLocals; + +import java.util.Collections; +import java.util.List; + +/** + * Always returns an empty list of suggestions. + */ +public class NullCompleter implements CommandCompleter { + + @Override + public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { + return Collections.emptyList(); + } + +} diff --git a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java index dd96c4a2a..c7b94ebde 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java +++ b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java @@ -27,7 +27,9 @@ import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.util.auth.Authorizer; import com.sk89q.worldedit.util.auth.NullAuthorizer; import com.sk89q.worldedit.util.command.CommandCallable; +import com.sk89q.worldedit.util.command.CommandCompleter; import com.sk89q.worldedit.util.command.Dispatcher; +import com.sk89q.worldedit.util.command.NullCompleter; import com.sk89q.worldedit.util.command.binding.PrimitiveBindings; import com.sk89q.worldedit.util.command.binding.StandardBindings; import com.sk89q.worldedit.util.command.binding.Switch; @@ -57,6 +59,7 @@ public class ParametricBuilder { private final List invokeListeners = new ArrayList(); private final List exceptionConverters = new ArrayList(); private Authorizer authorizer = new NullAuthorizer(); + private CommandCompleter defaultCompleter = new NullCompleter(); /** * Create a new builder. @@ -225,4 +228,26 @@ public class ParametricBuilder { checkNotNull(authorizer); this.authorizer = authorizer; } + + /** + * Get the default command suggestions provider that will be used if + * no suggestions are available. + * + * @return the default command completer + */ + public CommandCompleter getDefaultCompleter() { + return defaultCompleter; + } + + /** + * Set the default command suggestions provider that will be used if + * no suggestions are available. + * + * @param defaultCompleter the default command completer + */ + public void setDefaultCompleter(CommandCompleter defaultCompleter) { + checkNotNull(defaultCompleter); + this.defaultCompleter = defaultCompleter; + } + } diff --git a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java index a96434ac0..5a7836264 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java +++ b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java @@ -41,7 +41,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -273,8 +272,8 @@ class ParametricCallable implements CommandCallable { } @Override - public List getSuggestions(String stringArguments, CommandLocals locals) throws CommandException { - return Collections.emptyList(); + public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { + return builder.getDefaultCompleter().getSuggestions(arguments, locals); } /**