From 2d174f81c07c2a3e35b3f16b4ec403bc9624fae7 Mon Sep 17 00:00:00 2001 From: ORelio Date: Sat, 20 Jul 2013 12:58:41 +0200 Subject: [PATCH] Rewrite Scripting bot respecting the Bot API + Code Optimization Do NOT put thread sleeps in bots. NEVER. Initialize() and Update() are called in the main thread! Also, a delay should be respected between each chat/command sendind to avoid being kicked. Putting Thread.Sleep() in bots may cause the client to be out of sync with the server or make it lose connection so again do not use them :) --- MinecraftClient/Bots.cs | 100 ++++++++++++-------- MinecraftClient/McTcpClient.cs | 5 - MinecraftClient/MinecraftClient.csproj.user | 2 +- MinecraftClient/Program.cs | 42 ++++---- MinecraftClient/config/testscript.txt | 4 + 5 files changed, 86 insertions(+), 67 deletions(-) create mode 100644 MinecraftClient/config/testscript.txt diff --git a/MinecraftClient/Bots.cs b/MinecraftClient/Bots.cs index 234acbe0..23aa41b2 100644 --- a/MinecraftClient/Bots.cs +++ b/MinecraftClient/Bots.cs @@ -848,11 +848,14 @@ namespace MinecraftClient /// Script must be placed in the config directory /// - public class scripting : ChatBot + public class Scripting : ChatBot { private string file; private string[] lines = new string[0]; - public scripting(string filename) + private int sleepticks = 10; + private int sleepticks_interval = 10; + private int nextline = 0; + public Scripting(string filename) { file = filename; } @@ -862,48 +865,65 @@ namespace MinecraftClient // Loads the given file from the startup parameters if (System.IO.File.Exists("config/" + file)) { + LogToConsole("Loading script: \"" + file + "\""); lines = System.IO.File.ReadAllLines("config/" + file); // Load the given bot text file (containing commands) - for (int i = 0; i < lines.Length; i++) // Parse through each line of the bot text file - { - System.Threading.Thread.Sleep(100); - - string this_line = lines[i].Trim(); // Removes all whitespaces at start and end of current line - - if (this_line.Length == 0) - { - // Skip a completely empty line - } - else if (this_line.Trim().StartsWith("//")) - { - Console.ForegroundColor = ConsoleColor.DarkGray; - Console.WriteLine("BOT:" + this_line); - Console.ForegroundColor = ConsoleColor.Gray; - // Don't do anything for a comment line, denoted by '//' - } - else if (this_line.StartsWith("send ")) - { - Console.ForegroundColor = ConsoleColor.Gray; - SendText((lines[i].Trim().Substring(5, lines[i].Length - 5))); - // Send the command - } - else if (this_line.StartsWith("wait ")) - { - Console.ForegroundColor = ConsoleColor.DarkGray; - Console.WriteLine("BOT:Pausing for " + Convert.ToInt32(lines[i].Substring(5, lines[i].Length - 5)) * 100 + "ms..."); - Console.ForegroundColor = ConsoleColor.Gray; - System.Threading.Thread.Sleep(Convert.ToInt32(lines[i].Substring(5, lines[i].Length - 5)) * 100); - // Do a wait (given in milliseconds) - } - else if (this_line.StartsWith("exit")) - { - Program.B_Client.Disconnect(); - } // Optional exit only if called in bot text file, - } - UnloadBot(); // Otherwise continue operation of Client to normal (non-bot) usage } else { - Console.WriteLine(file + " not found! Please make sure that the file is located in the config directory."); + LogToConsole("File \"" + file + "\" not found in the config directory!"); + UnloadBot(); //No need to keep the bot active + } + } + + public override void Update() + { + if (sleepticks > 0) { sleepticks--; } + else + { + if (nextline < lines.Length) //Is there an instruction left to interpret? + { + string instruction_line = lines[nextline].Trim(); // Removes all whitespaces at start and end of current line + nextline++; //Move the cursor so that the next time the following line will be interpreted + sleepticks = sleepticks_interval; //Used to delay next command sending and prevent from beign kicked for spamming + + if (instruction_line.Length > 0) + { + if (instruction_line.Trim().StartsWith("//")) + { + LogToConsole(instruction_line); //Ignore comments but write them to the console + } + else + { + string instruction_name = instruction_line.Split(' ')[0]; + switch (instruction_name.ToLower()) + { + case "send": + SendText(instruction_line.Substring(5, instruction_line.Length - 5)); + break; + case "wait": + int ticks = 10; + try + { + ticks = Convert.ToInt32(instruction_line.Substring(5, instruction_line.Length - 5)); + } + catch {} + LogToConsole("Waiting " + ticks / 10 + " seconds..."); + sleepticks = ticks; + break; + case "disconnect": + Program.Exit(); + break; + case "exit": //Exit bot & stay connected to the server + UnloadBot(); + break; + } + } + } + } + else + { + //No more instructions to interpret + } } } } diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index 3cdebfa2..76d20d08 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -156,11 +156,6 @@ namespace MinecraftClient { while (client.Client.Connected) { - if (Program.scripting_enabled) - { - handler.BotLoad(new Bots.scripting(Program.scripting_param)); - Program.scripting_enabled = false; - } text = ConsoleIO.ReadLine(); if (text == "/quit" || text == "/reco" || text == "/reconnect") { break; } while (text.Length > 0 && text[0] == ' ') { text = text.Substring(1); } diff --git a/MinecraftClient/MinecraftClient.csproj.user b/MinecraftClient/MinecraftClient.csproj.user index 40f6ad1f..c1a6d7e8 100644 --- a/MinecraftClient/MinecraftClient.csproj.user +++ b/MinecraftClient/MinecraftClient.csproj.user @@ -1,7 +1,7 @@  - user - 127.0.0.1 bot:scripting + TestBot - localhost bot:scripting:testscript.txt publish\ diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 058b12ac..cfd85088 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -13,12 +13,7 @@ namespace MinecraftClient class Program { - // Scripting Bot Parameters - bearbear12345 - public static bool scripting_enabled; - public static string scripting_param; - // End Scripting Bot Parameters private static McTcpClient Client; - public static McTcpClient B_Client; private static string loginusername = ""; private static string user = ""; private static string pass = ""; @@ -206,22 +201,8 @@ namespace MinecraftClient #endregion handler.BotLoad(new Bots.AutoRelog(delay, retries)); break; - case "xauth": - if (botargs.Length > 2) { handler.BotLoad(new Bots.xAuth(botargs[2])); } break; - case "scripting": - if (botargs.Length > 2) - { - scripting_enabled = true; - scripting_param = botargs[2]; - //handler.BotLoad(new Bots.scripting(botargs[2])); - } - else - { - scripting_enabled = true; - scripting_param = "scripting.txt"; - //Launches later on after connected in MinecraftCom.cs - } - break; + case "xauth": if (botargs.Length > 2) { handler.BotLoad(new Bots.xAuth(botargs[2])); } break; + case "scripting": if (botargs.Length > 2) { handler.BotLoad(new Bots.Scripting(botargs[2])); } break; } command = ""; } @@ -271,6 +252,15 @@ namespace MinecraftClient new System.Threading.Thread(new System.Threading.ThreadStart(t_restart)).Start(); } + /// + /// Disconnect the current client from the server and exit the app + /// + + public static void Exit() + { + new System.Threading.Thread(new System.Threading.ThreadStart(t_exit)).Start(); + } + /// /// Pause the program, usually when an error or a kick occured, letting the user press Enter to quit OR type /reconnect /// @@ -297,5 +287,15 @@ namespace MinecraftClient Console.WriteLine("Restarting Minecraft Console Client..."); InitializeClient(); } + + /// + /// Private thread for exiting the program. Called through Exit() + /// + + private static void t_exit() + { + if (Client != null) { Client.Disconnect(); ConsoleIO.Reset(); } + Environment.Exit(0); + } } } diff --git a/MinecraftClient/config/testscript.txt b/MinecraftClient/config/testscript.txt new file mode 100644 index 00000000..0b829700 --- /dev/null +++ b/MinecraftClient/config/testscript.txt @@ -0,0 +1,4 @@ +send Hello World! I'm a bot. +wait 60 +send Now quitting :) +disconnect \ No newline at end of file