diff --git a/MinecraftClient/ConsoleIO.cs b/MinecraftClient/ConsoleIO.cs index 8ddc0261..1eb9c716 100644 --- a/MinecraftClient/ConsoleIO.cs +++ b/MinecraftClient/ConsoleIO.cs @@ -13,6 +13,8 @@ namespace MinecraftClient public static class ConsoleIO { public static void Reset() { if (reading) { reading = false; Console.Write("\b \b"); } } + public static void SetAutoCompleteEngine(IAutoComplete engine) { autocomplete_engine = engine; } + private static IAutoComplete autocomplete_engine; private static LinkedList previous = new LinkedList(); private static string buffer = ""; private static string buffer2 = ""; @@ -87,6 +89,20 @@ namespace MinecraftClient } break; case ConsoleKey.Tab: + if (autocomplete_engine != null && buffer.Length > 0) + { + string[] tmp = buffer.Split(' '); + if (tmp.Length > 0) + { + string word_tocomplete = tmp[tmp.Length - 1]; + string word_autocomplete = autocomplete_engine.AutoComplete(word_tocomplete); + if (!String.IsNullOrEmpty(word_autocomplete) && word_autocomplete != word_tocomplete) + { + while (buffer.Length > 0 && buffer[buffer.Length - 1] != ' ') { RemoveOneChar(); } + foreach (char c in word_autocomplete) { AddChar(c); } + } + } + } break; default: AddChar(k.KeyChar); @@ -215,4 +231,14 @@ namespace MinecraftClient } #endregion } + + /// + /// Interface for TAB autocompletion + /// Allows to use any object which has an AutoComplete() method using the IAutocomplete interface + /// + + public interface IAutoComplete + { + string AutoComplete(string BehindCursor); + } } diff --git a/MinecraftClient/MinecraftCom.cs b/MinecraftClient/MinecraftCom.cs index fa368ec4..94eefcae 100644 --- a/MinecraftClient/MinecraftCom.cs +++ b/MinecraftClient/MinecraftCom.cs @@ -11,7 +11,7 @@ namespace MinecraftClient /// The class containing all the core functions needed to communicate with a Minecraft server. /// - public class MinecraftCom + public class MinecraftCom : IAutoComplete { #region Login to Minecraft.net, Obtaining a session ID @@ -257,7 +257,7 @@ namespace MinecraftClient break; case 0xC9: readNextString(); readData(3); break; case 0xCA: if (protocolversion >= 72) { readData(9); } else readData(3); break; - case 0xCB: readNextString(); break; + case 0xCB: autocomplete_result = readNextString(); autocomplete_received = true; break; case 0xCC: readNextString(); readData(4); break; case 0xCD: readData(1); break; case 0xCE: if (protocolversion > 51) { readNextString(); readNextString(); readData(1); } break; @@ -484,6 +484,30 @@ namespace MinecraftClient Console.ForegroundColor = ConsoleColor.Gray; } + private bool autocomplete_received = false; + private string autocomplete_result = ""; + public string AutoComplete(string behindcursor) + { + if (String.IsNullOrEmpty(behindcursor)) + return ""; + + byte[] autocomplete = new byte[3 + (behindcursor.Length * 2)]; + autocomplete[0] = 0xCB; + byte[] msglen = BitConverter.GetBytes((short)behindcursor.Length); + Array.Reverse(msglen); msglen.CopyTo(autocomplete, 1); + byte[] msg = Encoding.BigEndianUnicode.GetBytes(behindcursor); + msg.CopyTo(autocomplete, 3); + + autocomplete_received = false; + autocomplete_result = behindcursor; + Send(autocomplete); + + int wait_left = 50; //do not wait more than 5 seconds (50 * 100 ms) + while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; } + string[] results = autocomplete_result.Split((char)0x00); + return results[0]; + } + public void setVersion(byte ver) { protocolversion = ver; } public void setClient(TcpClient n) { c = n; } private void setEncryptedClient(Crypto.AesStream n) { s = n; encrypted = true; } diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index def8912f..6258195e 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -123,6 +123,7 @@ namespace MinecraftClient //Will handle the connection for this client Console.WriteLine("Version is supported."); MinecraftCom handler = new MinecraftCom(); + ConsoleIO.SetAutoCompleteEngine(handler); handler.setVersion(protocolversion); //Load & initialize bots if needed