using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MinecraftClient { /// /// Welcome to the Bot API file ! /// The virtual class "ChatBot" contains anything you need for creating chat bots /// Inherit from this class while adding your bot class to the folder "Bots". /// Once your bot is created, read the explanations below to start using it in the MinecraftClient app. /// /// Pieces of code to add in other parts of the program for your bot. Line numbers are approximative. /// McTcpClient:110 | if (Settings.YourBot_Enabled) { handler.BotLoad(new ChatBots.YourBot()); } /// Settings.cs:73 | public static bool YourBot_Enabled = false; /// Settings.cs:74 | private enum ParseMode { /* [...] */, YourBot }; /// Settings.cs:106 | case "yourbot": pMode = ParseMode.YourBot; break; /// Settings.cs:197 | case ParseMode.YourBot: switch (argName.ToLower()) { case "enabled": YourBot_Enabled = str2bool(argValue); break; } break; /// Settings.cs:267 | + "[YourBot]\r\n" + "enabled=false\r\n" /// Here your are. Now you will have a setting in MinecraftClient.ini for enabling your brand new bot. /// Delete MinecraftClient.ini to re-generate it or add the lines [YourBot] and enabled=true to the existing one. /// /// /// The virtual class containing anything you need for creating chat bots. /// public abstract class ChatBot { public enum DisconnectReason { InGameKick, LoginRejected, ConnectionLost }; //Will be automatically set on bot loading, don't worry about this public void SetHandler(McTcpClient handler) { this.handler = handler; } private McTcpClient handler; /* ================================================== */ /* Main methods to override for creating your bot */ /* ================================================== */ /// /// Anything you want to initialize your bot, will be called on load by MinecraftCom /// public virtual void Initialize() { } /// /// Will be called every ~100ms (10fps) if loaded in MinecraftCom /// public virtual void Update() { } /// /// Any text sent by the server will be sent here by MinecraftCom /// /// Text from the server public virtual void GetText(string text) { } /// /// Is called when the client has been disconnected fom the server /// /// Disconnect Reason /// Kick message, if any /// Return TRUE if the client is about to restart public virtual bool OnDisconnect(DisconnectReason reason, string message) { return false; } /* =================================================================== */ /* ToolBox - Methods below might be useful while creating your bot. */ /* You should not need to interact with other classes of the program. */ /* =================================================================== */ /// /// Send text to the server. Can be anything such as chat messages or commands /// /// Text to send to the server /// True if the text was sent with no error protected bool SendText(string text) { ConsoleIO.WriteLineFormatted("§8BOT:" + text, false); return handler.SendChatMessage(text); } /// /// Check if the given command is a valid internal MCC command /// /// The command or command name /// TRUE if this is an internal command protected bool isInternalCommand(string command) { return handler.isInternalCommand(command); } /// /// Perform an internal MCC command (not a server command, use SendText() instead for that!) /// /// The command /// TRUE if the command was successfully recognized and performed protected bool performInternalCommand(string command) { return handler.performInternalCommand(command); } /// /// Remove color codes ("§c") from a text message received from the server /// protected static string getVerbatim(string text) { if ( String.IsNullOrEmpty(text) ) return String.Empty; int idx = 0; var data = new char[text.Length]; for ( int i = 0; i < text.Length; i++ ) if ( text[i] != '§' ) data[idx++] = text[i]; else i++; return new string(data, 0, idx); } /// /// Verify that a string contains only a-z A-Z 0-9 and _ characters. /// protected static bool isValidName(string username) { if ( String.IsNullOrEmpty(username) ) return false; foreach ( char c in username ) if ( !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') ) return false; return true; } /// /// Returns true if the text passed is a private message sent to the bot /// /// text to test /// if it's a private message, this will contain the message /// if it's a private message, this will contain the player name that sends the message /// Returns true if the text is a private message protected static bool isPrivateMessage(string text, ref string message, ref string sender) { text = getVerbatim(text); if (text == "") { return false; } string[] tmp = text.Split(' '); try { //Detect vanilla /tell messages //Someone whispers message (MC 1.5) //Someone whispers to you: message (MC 1.7) if (tmp.Length > 2 && tmp[1] == "whispers") { if (tmp.Length > 4 && tmp[2] == "to" && tmp[3] == "you:") { message = text.Substring(tmp[0].Length + 18); //MC 1.7 } else message = text.Substring(tmp[0].Length + 10); //MC 1.5 sender = tmp[0]; return isValidName(sender); } //Detect Essentials (Bukkit) /m messages //[Someone -> me] message else if (text[0] == '[' && tmp.Length > 3 && tmp[1] == "->" && (tmp[2] == "me]" || tmp[2] == "moi]")) //'me' is replaced by 'moi' in french servers { message = text.Substring(tmp[0].Length + 4 + tmp[2].Length + 1); sender = tmp[0].Substring(1); if (sender[0] == '~') { sender = sender.Substring(1); } return isValidName(sender); } else return false; } catch (IndexOutOfRangeException) { return false; } } /// /// Returns true if the text passed is a public message written by a player on the chat /// /// text to test /// if it's message, this will contain the message /// if it's message, this will contain the player name that sends the message /// Returns true if the text is a chat message protected static bool isChatMessage(string text, ref string message, ref string sender) { //Detect chat messages // message //<*Faction Someone> message //<*Faction Someone>: message //<*Faction ~Nicknamed>: message text = getVerbatim(text); if (text == "") { return false; } if (text[0] == '<') { try { text = text.Substring(1); string[] tmp = text.Split('>'); sender = tmp[0]; message = text.Substring(sender.Length + 2); if (message.Length > 1 && message[0] == ' ') { message = message.Substring(1); } tmp = sender.Split(' '); sender = tmp[tmp.Length - 1]; if (sender[0] == '~') { sender = sender.Substring(1); } return isValidName(sender); } catch (IndexOutOfRangeException) { return false; } } else return false; } /// /// Returns true if the text passed is a teleport request (Essentials) /// /// Text to parse /// Will contain the sender's username, if it's a teleport request /// Returns true if the text is a teleport request protected static bool isTeleportRequest(string text, ref string sender) { text = getVerbatim(text); sender = text.Split(' ')[0]; if (text.EndsWith("has requested to teleport to you.") || text.EndsWith("has requested that you teleport to them.")) { return isValidName(sender); } else return false; } /// /// Writes some text in the console. Nothing will be sent to the server. /// /// Log text to write public static void LogToConsole(string text) { ConsoleIO.WriteLineFormatted("§8[BOT] " + text); } /// /// Disconnect from the server and restart the program /// It will unload & reload all the bots and then reconnect to the server /// protected void ReconnectToTheServer() { ReconnectToTheServer(3); } /// /// Disconnect from the server and restart the program /// It will unload & reload all the bots and then reconnect to the server /// /// If connection fails, the client will make X extra attempts protected void ReconnectToTheServer(int ExtraAttempts) { McTcpClient.AttemptsLeft = ExtraAttempts; Program.Restart(); } /// /// Disconnect from the server and exit the program /// protected void DisconnectAndExit() { Program.Exit(); } /// /// Unload the chatbot, and release associated memory. /// protected void UnloadBot() { handler.BotUnLoad(this); } /// /// Send a private message to a player /// /// Player name /// Message protected void SendPrivateMessage(string player, string message) { SendText("/tell " + player + ' ' + message); } /// /// Run a script from a file using a Scripting bot /// /// File name /// Player name to send error messages, if applicable protected void RunScript(string filename, string playername = "") { handler.BotLoad(new ChatBots.Script(filename, playername)); } } }