diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java index 1ff7dd67..4178f522 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Stack; import java.util.jar.JarEntry; @@ -75,6 +76,11 @@ public class PluginManager commandMap.values().remove( command ); } + public boolean dispatchCommand(CommandSender sender, String commandLine) + { + return dispatchCommand( sender, commandLine, null ); + } + /** * Execute a command if it is registered, else return false. * @@ -83,7 +89,7 @@ public class PluginManager * arguments * @return whether the command was handled */ - public boolean dispatchCommand(CommandSender sender, String commandLine) + public boolean dispatchCommand(CommandSender sender, String commandLine, List tabResults) { String[] split = argsSplit.split( commandLine ); // Check for chat that only contains " " @@ -113,7 +119,13 @@ public class PluginManager String[] args = Arrays.copyOfRange( split, 1, split.length ); try { - command.execute( sender, args ); + if ( tabResults == null ) + { + command.execute( sender, args ); + } else if ( command instanceof TabExecutor ) + { + tabResults.addAll( ( (TabExecutor) command ).onTabComplete( sender, args ) ); + } } catch ( Exception ex ) { sender.sendMessage( ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details." ); diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/TabExecutor.java b/api/src/main/java/net/md_5/bungee/api/plugin/TabExecutor.java new file mode 100644 index 00000000..2510573e --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/plugin/TabExecutor.java @@ -0,0 +1,11 @@ +package net.md_5.bungee.api.plugin; + +import net.md_5.bungee.api.CommandSender; + +import java.util.List; + +public interface TabExecutor +{ + + public List onTabComplete(CommandSender sender, String[] args); +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Vanilla.java b/protocol/src/main/java/net/md_5/bungee/protocol/Vanilla.java index df3bf212..8d5ef719 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Vanilla.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Vanilla.java @@ -13,6 +13,7 @@ import net.md_5.bungee.protocol.packet.Packet2Handshake; import net.md_5.bungee.protocol.packet.Packet3Chat; import net.md_5.bungee.protocol.packet.Packet9Respawn; import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem; +import net.md_5.bungee.protocol.packet.PacketCBTabComplete; import net.md_5.bungee.protocol.packet.PacketCCSettings; import net.md_5.bungee.protocol.packet.PacketCDClientStatus; import net.md_5.bungee.protocol.packet.PacketCEScoreboardObjective; @@ -56,6 +57,7 @@ public class Vanilla implements Protocol classes[0xC9] = PacketC9PlayerListItem.class; classes[0x2C] = Packet2CEntityProperties.class; classes[0xCC] = PacketCCSettings.class; + classes[0xCB] = PacketCBTabComplete.class; classes[0xCD] = PacketCDClientStatus.class; classes[0xCE] = PacketCEScoreboardObjective.class; classes[0xCF] = PacketCFScoreboardScore.class; diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java index 795661f2..7c2cf698 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/AbstractPacketHandler.java @@ -74,4 +74,8 @@ public abstract class AbstractPacketHandler public void handle(PacketFFKick kick) throws Exception { } + + public void handle(PacketCBTabComplete tabComplete) throws Exception + { + } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PacketCBTabComplete.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PacketCBTabComplete.java new file mode 100644 index 00000000..0e2dcaa8 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PacketCBTabComplete.java @@ -0,0 +1,56 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +@Getter +@ToString +@EqualsAndHashCode(callSuper = false) +public class PacketCBTabComplete extends DefinedPacket +{ + + private String cursor; + private String[] commands; + + private PacketCBTabComplete() + { + super( 0xCB ); + } + + public PacketCBTabComplete(String[] alternatives) + { + this(); + commands = alternatives; + } + + @Override + public void read(ByteBuf buf) + { + cursor = readString( buf ); + } + + @Override + public void write(ByteBuf buf) + { + String tab = ""; + for ( String alternative : commands ) + { + if ( tab.isEmpty() ) + { + tab = alternative + " "; + } else + { + tab += "\0" + alternative + " "; + } + } + writeString( tab, buf ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index f6d38116..0421905f 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -13,8 +13,11 @@ import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PacketWrapper; import net.md_5.bungee.protocol.packet.Packet0KeepAlive; import net.md_5.bungee.protocol.packet.Packet3Chat; +import net.md_5.bungee.protocol.packet.PacketCBTabComplete; import net.md_5.bungee.protocol.packet.PacketCCSettings; import net.md_5.bungee.protocol.packet.PacketFAPluginMessage; +import java.util.ArrayList; +import java.util.List; public class UpstreamBridge extends PacketHandler { @@ -89,6 +92,18 @@ public class UpstreamBridge extends PacketHandler throw new CancelSendSignal(); } + @Override + public void handle(PacketCBTabComplete tabComplete) throws Exception + { + if ( tabComplete.getCursor().startsWith( "/" ) ) + { + List results = new ArrayList<>(); + bungee.getPluginManager().dispatchCommand( con, tabComplete.getCursor(), results ); + con.unsafe().sendPacket( new PacketCBTabComplete( results.toArray( new String[ results.size() ] ) ) ); + throw new CancelSendSignal(); + } + } + @Override public void handle(PacketCCSettings settings) throws Exception {