public void Start(TcpClient RClient, Server server) { //Test rTcpClient = RClient; reader = new BinaryReader(rTcpClient.GetStream()); writer = new BinaryWriter(rTcpClient.GetStream()); int failedTries = 0; byte[] OpCodePacket= new byte[1]; int bytesRead; while (true) { bytesRead = 0; try { //blocks until a client sends a message bytesRead = rTcpClient.Client.Receive(OpCodePacket,1,SocketFlags.None); switch((RemoteProtocol)OpCodePacket[0]) { case RemoteProtocol.Username: //Username { Username = reader.ReadString(); writer.Write((byte)RemoteProtocol.ServerMessage); writer.Write((byte)3); writer.Write("Hello "+Username+". Please enter the password sent to you by the bot owner to use the bot."); break; } case RemoteProtocol.Password: { if(Username == null) throw new SocketException(-1); if(failedTries > 3) { writer.Write((byte)RemoteProtocol.ServerMessage); writer.Write((byte)2); writer.Write("You have incorrectly guessed the password more than three times. The session has been closed."); throw new SocketException(-1); } string Password = reader.ReadString(); if(server._password != Password) { writer.Write((byte)RemoteProtocol.ServerMessage); writer.Write((byte)4); writer.Write("Incorrect password. You have " + (3 - failedTries).ToString() + " more tries."); failedTries++; } else { Authorised = true; writer.Write((byte)RemoteProtocol.ClientAuthorised); writer.Write("You have now been authenticated"); RemoteLoginEventArgs e = new RemoteLoginEventArgs(Username,(IPEndPoint)rTcpClient.Client.RemoteEndPoint,rTcpClient); server.MinecraftBot.Events.RaiseUserLoggedIn(e); } break; } case RemoteProtocol.IncomingMessage: { string chat = reader.ReadString(); if(chat.StartsWith("&")) { string commandname = chat.TrimStart('&').Split(' ')[0]; string args = String.Empty; try { args = chat.Substring(commandname.Length + 2); } catch { }//Account for first white variable. args.TrimStart(' '); writer.Write((byte)RemoteProtocol.ServerResponse); switch(commandname) { case "commands": { writer.Write((byte)0); writer.Write("Commands: " +Environment.NewLine + "&commands - Returns a list of commands." + Environment.NewLine + "&players - Returns a list of players on the same map as the bot." + Environment.NewLine + "&listlogs - Returns a list of all log files in the bot directory." + Environment.NewLine + "&getlog - Gets the log file from the specified name."); break; } case "players": { writer.Write((byte)0); Dictionary<byte, Player> players = server.MinecraftBot.Players; List<string> Output = new List<string>(); foreach(Player player in players.Values) { Output.Add(player.Name); } string[] output = Output.ToArray(); writer.Write("Players in the current map: " +Environment.NewLine + string.Join(",",output)); } break; case "listlogs": { writer.Write((byte)0); string[] rawFiles = Directory.GetFiles(Directory.GetCurrentDirectory()); List<String> Files = new List<string>(rawFiles); System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach(string file in Files) { string fileRelative = Path.GetFileName(file); if(fileRelative.StartsWith("log-")) sb.Append(fileRelative + Environment.NewLine); } writer.Write("Log files: " + Environment.NewLine + sb); break; } case "getlog": { string reqFile = Path.Combine(Directory.GetCurrentDirectory(),args); string[] rawFiles = Directory.GetFiles(Directory.GetCurrentDirectory()); List<string> Files = new List<string>(rawFiles); if(!Files.Contains(reqFile)) { writer.Write((byte)0); writer.Write("No file matching "+args + " found. You must include the extension as well."); } else { writer.Write((byte)1); writer.Write(Path.GetFileName(reqFile)); writer.Write(File.ReadAllText(reqFile)); } //writer.Write("Test."); break; } default: { writer.Write((byte)0); writer.Write("Unknown command: " +chat.TrimStart('&').Split(' ')[0] + ". To see a list of commands, type &commands"); break; } } break; } //If the user wishes to do a server command. if(Authorised) //Only send if authorised, still read the message otherwise we become out of sync with the client. { Extensions.StripColors(chat); server.MinecraftBot.SendLongChat(chat); } break; } default: throw new SocketException(-1); } } catch { //A socket error has occured, don't log why. break; } if (bytesRead == 0) { //The client has disconnected. break; } } SessionEndedEventArgs endede = new SessionEndedEventArgs(Username); server.MinecraftBot.Events.RaiseSessionEnded(endede); if(rTcpClient != null) { rTcpClient.Client.Disconnect(true); rTcpClient.Close(); } }
/// <summary> Loads configuration settings from a file called botsettings.txt </summary> private void LoadConfig() { try { config = new Config( "botsettings.txt" ); if( !config.Exists() ) { using( StreamWriter sw = new StreamWriter( "botsettings.txt" ) ) { sw.WriteLine("UseRemoteServer: false"); sw.WriteLine("RemotePort: "); sw.WriteLine("RemotePassword: "******"CommandsRequireOperator: true"); sw.WriteLine("ReconnectAfterKick: true"); sw.WriteLine("SaveMap: false"); sw.WriteLine("Operators:"); sw.WriteLine("#And now, a little explaination on what all these mean."); sw.WriteLine("#UseRemoteServer - Allows remote clients to connect and perform actions on the bot / chat through it. By default, this is disabled." + "If you choose to use the remote function, you may need to forward the port and/or add an exception to your firewall."); sw.WriteLine("#RemotePort - The port the server will listen on for remote clients. It is fine to leave this blank if UseRemoteServer is false."); sw.WriteLine("#RemotePassword - The password to use for verifying remote clients. " + "If UseRemoteServer is true and this is blank, the password will be set to \"password\". "); sw.WriteLine("#CommandsRequireOperators - This determines whether bot commands require the person who called them to be in the operators file." + "Usually you would want this to be true."); sw.WriteLine("#ReconnectAfterKick - This determines if the bot will reconnect after being kicked. Note that if the bot receives a kick packet before" + "a ServerIdentification packet, it will abort, and assume it has been banned from connecting."); sw.WriteLine("#SaveMap - This determines if the bot will save the map when the chunk packets are sent to it." + "If this is true, it will be saved as a fCraft compatible map. (Large maps of 512 x 512 x 512 " + "can use up to ~150 megabytes of RAM when saving, so be wary. After saving, memory usage should return to normal."); sw.WriteLine( "#Operators: Comma separated list of operators, with no spaces. (e.g. test,test1,test2)" ); Events.RaiseConfigCreating( new ConfigCreatingEventArgs( config, sw ) ); } } config.Load(); if( !config.TryParseValueOrDefault( "useremoteserver", false, out UseRemoteServer ) ) Log( LogType.Warning, "Couldn't load value for useremoteserver from config. Setting to default value of false" ); if( UseRemoteServer ) { int remotePort; if( !config.TryParseValueOrDefault( "remoteport", 25561, out remotePort ) ) { Log( LogType.Warning, "Couldn't load value for remoteport from config. Setting to default value of 25561" ); } string remotePassword; config.TryGetRawValue( "remotepassword", out remotePassword ); if( String.IsNullOrEmpty( remotePassword ) ) { remotePassword = "******"; Log( LogType.Warning, "Couldn't load value for remotepassword from config. Setting to default value of \"password\"" ); } server = new Server(); server.Start( this, remotePort, remotePassword ); } if( !config.TryParseValueOrDefault( "commandsrequireoperator", true, out _requiresop ) ) Log( LogType.Warning, "Couldn't load value for commandsrequireoperator from config. Setting to default value of true" ); if( !config.TryParseValueOrDefault( "reconnectafterkick", true, out _reconnectonkick ) ) Log( LogType.Warning, "Couldn't load value for reconnectafterkick from config. Setting to default value of true" ); if( !config.TryParseValueOrDefault( "savemap", false, out _savemap ) ) Log( LogType.Warning, "Couldn't load value for savemap from config. Setting to default value of false" ); string rawUsers; // Comma separated. config.TryGetRawValue( "operators", out rawUsers ); if( String.IsNullOrEmpty( rawUsers ) ) { Log( LogType.Warning, "Couldn't load value for operators from config. Setting to default value of empty." ); } else { string[] users = rawUsers.Split( ',' ); bool fixedNames = false; for( int i = 0; i < users.Length; i++ ) { if( users[i].IndexOf( ' ' ) != -1 ) { fixedNames = true; users[i] = users[i].Replace( " ", String.Empty ); } } if( fixedNames ) { config.AddOrUpdateValue( "operators", String.Join( ",", users ) ); Log( LogType.BotActivity, "Fixed up spaces in the list of operators." ); config.Save(); } Users.AddRange( users ); } Events.RaiseConfigLoading( new ConfigLoadingEventArgs( config ) ); } catch( Exception e ) { Log( LogType.Error, "Couldn't load config:", e.ToString() ); } }