diff --git a/MinecraftClient/config/Modules/Mail.cs b/MinecraftClient/config/Modules/Mail.cs
new file mode 100644
index 00000000..d1547d0a
--- /dev/null
+++ b/MinecraftClient/config/Modules/Mail.cs
@@ -0,0 +1,560 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Data;
+using System.Data.SqlClient;
+using System.Text;
+using System.Runtime.Serialization.Formatters;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.IO;
+
+namespace MinecraftClient.ChatBots
+{
+ ///
+ /// All saved options.
+ ///
+ [Serializable]
+ class Options
+ {
+ public string path_mail { get; set; }
+ public string path_setting { get; set; }
+ public string botname { get; set; }
+ public int interval_sendmail { get; set; }
+ public int maxSavedMails { get; set; }
+ public int maxSavedMails_Player { get; set; }
+ public int daysTosaveMsg { get; set; }
+ public bool debug_msg { get; set; }
+ public string[] moderator = new string[1];
+ public DateTime lastReset { get; set; }
+ public int timevar_100ms { get; set; }
+
+ public Options()
+ {
+ path_mail = Path.GetFullPath(@"\mails.txt"); // Path where the mail file is saved. You can also apply a normal path like @"C:\Users\SampleUser\Desktop"
+ path_setting = Path.GetFullPath(@"\options.txt"); // Path where the settings are saved
+ botname = "Chatie"; // Ingamename of the bot
+ moderator[0] = "daenges"; // Enter your own MC name. !!! CAUTION !!! Who you give mod previliges!
+ interval_sendmail = 100; // Intervall atempting to send mails / do a respawn [in 100 ms] -> eg. 100 * 100ms = 10 sec
+ maxSavedMails = 2000; // How many mails you want to safe
+ maxSavedMails_Player = 3; // How many mails can be sent per player
+ daysTosaveMsg = 30; // After how many days the message should get deleted
+ debug_msg = true; // Disable debug Messages for a cleaner console
+
+ timevar_100ms = 0;
+ lastReset = DateTime.UtcNow;
+ }
+ }
+
+ ///
+ /// The Way every mail is safed.
+ ///
+ [Serializable]
+ class Message
+ {
+ string sender;
+ string destination;
+ string content;
+ DateTime timestamp;
+ bool delivered;
+
+ public Message(string sender_1, string destination_1, string content_1)
+ {
+ sender = sender_1;
+ destination = destination_1;
+ content = content_1;
+ timestamp = DateTime.UtcNow;
+ delivered = false;
+ }
+
+ // Obtain Message data.
+ public string GetSender()
+ {
+ return sender;
+ }
+ public string GetDestination()
+ {
+ return destination;
+ }
+ public string GetContent()
+ {
+ return content;
+ }
+ public DateTime GetTimeStamp()
+ {
+ return timestamp;
+ }
+ public bool isDelivered()
+ {
+ return delivered;
+ }
+
+ // Set the message to "delivered" to clear the list later.
+ public void setDelivered()
+ {
+ delivered = true;
+ }
+ }
+
+
+
+
+ public class Mail : ChatBot
+ {
+ Message[] logged_msg;
+ Options options;
+
+ ///
+ /// Sets the message an option cache
+ ///
+ public override void Initialize()
+ {
+ logged_msg = new Message[0];
+ options = new Options();
+ }
+
+
+ ///
+ /// Standard settings for the bot.
+ ///
+ public override void AfterGameJoined()
+ {
+ if (!File.Exists(options.path_setting))
+ {
+ SaveOptionsToFile();
+ }
+ else
+ {
+ GetOptionsFromFile();
+ }
+
+ if (!File.Exists(options.path_mail))
+ {
+ SaveMailsToFile();
+ }
+
+ deleteOldMails();
+ options.lastReset = DateTime.UtcNow;
+ }
+
+ ///
+ /// Timer for autorespawn and the message deliverer
+ ///
+ public override void Update()
+ {
+ if (options.timevar_100ms == options.interval_sendmail)
+ {
+ DeliverMail();
+ PerformInternalCommand("/respawn");
+
+ if ((DateTime.Now - options.lastReset).TotalDays > options.daysTosaveMsg)
+ {
+ deleteOldMails();
+ options.lastReset = DateTime.UtcNow;
+ }
+
+ options.timevar_100ms = 0;
+ }
+ options.timevar_100ms++;
+ }
+
+ ///
+ /// Listening for Messages.
+ ///
+ public override void GetText(string text)
+ {
+ string message = "";
+ string username = "";
+
+
+
+ text = GetVerbatim(text);
+
+
+
+ if (IsPrivateMessage(text, ref message, ref username) && username.ToLower() != options.botname)
+ {
+ message = message.ToLower();
+ cmd_reader(message, username, isMessageFromMod(username));
+ }
+
+ }
+
+ ///
+ /// Interprets command.
+ ///
+ public void cmd_reader(string message, string sender, bool isMod)
+ {
+ if (message.Contains("sendmail"))
+ {
+ GetMailsFromFile();
+ if (getSentMessagesByUser(sender) < options.maxSavedMails_Player && logged_msg.Length < options.maxSavedMails)
+ {
+
+
+ string content = "";
+ string destination = "";
+ bool destination_ended = false;
+
+ for (int i = message.IndexOf("sendmail") + 9; i < message.Length; i++) // + 4 -> get first letter of the name.
+ {
+ if (message[i] != Convert.ToChar(" ") && !destination_ended)
+ {
+ destination += message[i]; // extract destination
+ }
+ else
+ {
+ destination_ended = true;
+
+ content += message[i]; // extract message content
+ }
+ }
+
+ if (sender != string.Empty && destination != string.Empty && content != string.Empty)
+ {
+ AddMail(sender, destination, content);
+ }
+ }
+ else
+ {
+ SendPrivateMessage(sender, "Couldn't save Message. Limit reached!");
+ }
+ clearLogged_msg();
+ }
+
+ if (isMod)
+ {
+
+ // These commands can be exploited easily and may cause huge damage.
+
+
+ if (message.Contains("getmails"))
+ {
+ if (options.debug_msg)
+ {
+ LogToConsole("Listing all Messages. \n Performed by: " + sender);
+ }
+ GetMailsFromFile();
+ foreach (Message m in logged_msg)
+ {
+ LogToConsole(m.GetSender() + " " + m.GetDestination() + " " + m.GetContent() + " " + Convert.ToString(m.GetTimeStamp()));
+ }
+
+ clearLogged_msg();
+ }
+
+ /*
+ // Only uncomment for testing reasons
+
+ if (message.Contains("clearmails"))
+ {
+ if (debug_msg)
+ {
+ LogToConsole("Clearing Messages.");
+ }
+ clearSavedMails();
+ }
+ */
+
+
+
+ if (message.Contains("respawn"))
+ {
+ if (options.debug_msg)
+ {
+ LogToConsole("Respawning! \n Performed by: " + sender);
+ }
+ PerformInternalCommand("/respawn");
+ }
+
+ if (message.Contains("deliver"))
+ {
+ if (options.debug_msg)
+ {
+ LogToConsole("Sending Mails! \n Performed by: " + sender);
+ }
+ DeliverMail();
+ }
+
+ if (message.Contains("reconnect"))
+ {
+ if (options.debug_msg)
+ {
+ LogToConsole("Reconnecting! \n Performed by: " + sender);
+ }
+ ReconnectToTheServer();
+ }
+
+ if (message.Contains("addmod"))
+ {
+ string name = "";
+
+ for (int i = message.IndexOf("addMod") + 7; i < message.Length; i++)
+ {
+ if (message[i] != Convert.ToChar(" "))
+ {
+ name += message[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ addMod(name);
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Added " + name + " as moderator! \n Performed by: " + sender);
+ }
+ }
+
+ if (message.Contains("removemod"))
+ {
+ string name = "";
+
+
+ for (int i = message.IndexOf("addMod") + 7; i < message.Length; i++)
+ {
+ if (message[i] != Convert.ToChar(" "))
+ {
+ name += message[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ removeMod(name);
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Removed " + name + " as moderator! \n Performed by: " + sender);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Clear the safe File.
+ ///
+ public void clearSavedMails()
+ {
+ clearLogged_msg();
+ SaveMailsToFile();
+ }
+
+ ///
+ /// Clear the messages in ram.
+ ///
+ public void clearLogged_msg()
+ {
+ logged_msg = new Message[0];
+ }
+
+ ///
+ /// Add a player who can moderate the bot.
+ ///
+ public void addMod(string name)
+ {
+ string[] temp = options.moderator;
+ options.moderator = new string[options.moderator.Length + 1];
+
+ for (int i = 0; i < temp.Length; i++)
+ {
+ options.moderator[i] = temp[i];
+ }
+ options.moderator[options.moderator.Length - 1] = name;
+ }
+
+ ///
+ /// Remove a player from the moderator list.
+ ///
+ public void removeMod(string name)
+ {
+
+ for (int i = 0; i < options.moderator.Length; i++)
+ {
+ if (options.moderator[i] == name)
+ {
+ options.moderator[i] = string.Empty;
+ }
+ }
+ options.moderator = options.moderator.Where(x => !string.IsNullOrEmpty(x)).ToArray();
+ }
+
+ ///
+ /// Serialize mails to binary file.
+ ///
+ public void SaveMailsToFile()
+ {
+
+ BinaryFormatter formatter = new BinaryFormatter();
+ FileStream stream = new FileStream(options.path_mail, FileMode.Create, FileAccess.Write);
+
+ formatter.Serialize(stream, logged_msg);
+ stream.Close();
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Saved mails to File! \n" + "Location: " + options.path_mail + "\n Time: " + Convert.ToString(DateTime.UtcNow));
+ }
+ }
+
+ ///
+ /// Get mails from save file.
+ ///
+ public void GetMailsFromFile()
+ {
+
+ BinaryFormatter formatter = new BinaryFormatter();
+ FileStream stream = new FileStream(options.path_mail, FileMode.Open, FileAccess.Read);
+
+ logged_msg = (Message[])formatter.Deserialize(stream);
+ stream.Close();
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Loaded mails from File! \n" + "Location: " + options.path_mail + "\n Time: " + Convert.ToString(DateTime.UtcNow));
+ }
+ }
+
+ ///
+ /// Serialize settings to binary file.
+ ///
+ public void SaveOptionsToFile()
+ {
+
+ BinaryFormatter formatter = new BinaryFormatter();
+ FileStream stream = new FileStream(options.path_setting, FileMode.Create, FileAccess.Write);
+
+ formatter.Serialize(stream, options);
+ stream.Close();
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Saved options to File! \n" + "Location: " + options.path_setting + "\n Time: " + Convert.ToString(DateTime.UtcNow));
+ }
+ }
+
+ ///
+ /// Get settings from save file.
+ ///
+ public void GetOptionsFromFile()
+ {
+
+ BinaryFormatter formatter = new BinaryFormatter();
+ FileStream stream = new FileStream(options.path_setting, FileMode.Open, FileAccess.Read);
+
+ options = (Options)formatter.Deserialize(stream);
+ stream.Close();
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Loaded options from File! \n" + "Location: " + options.path_setting + "\n Time: " + Convert.ToString(DateTime.UtcNow));
+ }
+ }
+
+ ///
+ /// Add a message to the list.
+ ///
+ public void AddMail(string sender, string destination, string content)
+ {
+ GetMailsFromFile();
+
+ Message[] tmp = logged_msg;
+ logged_msg = new Message[logged_msg.Length + 1];
+
+ for (int i = 0; i < tmp.Length; i++)
+ {
+ logged_msg[i] = tmp[i];
+ }
+
+ logged_msg[logged_msg.Length - 1] = new Message(sender, destination, content);
+
+ SaveMailsToFile();
+ SendPrivateMessage(sender, "Message saved!");
+ }
+
+ ///
+ /// Try to send all messages.
+ ///
+ public void DeliverMail()
+ {
+ LogToConsole("Looking for mails to send:");
+ GetMailsFromFile();
+
+ foreach(string Player in GetOnlinePlayers())
+ {
+ foreach (Message msg in logged_msg)
+ {
+ if (Player.ToLower() == msg.GetDestination().ToLower() && !msg.isDelivered())
+ {
+ SendPrivateMessage(msg.GetDestination(), msg.GetSender() + " mailed: " + msg.GetContent());
+ msg.setDelivered();
+
+ if (options.debug_msg)
+ {
+ LogToConsole("Message of " + msg.GetSender() + " delivered to " + msg.GetDestination() + ".");
+ }
+ }
+ }
+ }
+
+ logged_msg = logged_msg.Where(x => !x.isDelivered()).ToArray();
+ SaveMailsToFile();
+ clearLogged_msg();
+ }
+
+ ///
+ /// See how many messages of a user are saved.
+ ///
+ public int getSentMessagesByUser(string player)
+ {
+ int mailcount = 0;
+
+ foreach (Message msg in logged_msg)
+ {
+ if (msg.GetSender() == player)
+ {
+ mailcount++;
+ }
+ }
+ return mailcount;
+ }
+
+ ///
+ /// Test if the sender is in the moderator list.
+ ///
+ public bool isMessageFromMod(string player)
+ {
+ foreach (string mod in options.moderator)
+ {
+ if (mod.ToLower() == player.ToLower())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Deleting mails older than a month.
+ ///
+ public void deleteOldMails()
+ {
+ GetMailsFromFile();
+
+ for(int i = 0; i < logged_msg.Length; i++)
+ {
+ if ((DateTime.UtcNow - logged_msg[i].GetTimeStamp()).TotalDays > options.daysTosaveMsg)
+ {
+ logged_msg[i].setDelivered();
+ }
+ }
+ logged_msg = logged_msg.Where(x => !x.isDelivered()).ToArray();
+ SaveMailsToFile();
+ clearLogged_msg();
+ }
+ }
+}