public static void InputInterpreter(Client commandingClient) { string clientInput = ""; // Pliant clients give silent compliance... string parsedCommand = ""; string adjustedClientInput = ""; List <string> commandList = new List <string> { "quit!", "dog", "say", "help", "chist", "lusers" }; List <string> adminCommandList = new List <string> { "nuser", "laccounts", "kick", "ban", "unban", "xmltest", "loadcheck", "findroom" }; List <string> verbList = new List <string> { "quit!", "say", "kick", "ban", "unban" }; clientInput = commandingClient.incoming.ReadLine(); // Get the input. ArrayList commandingClients = new ArrayList(); try { if (Regex.Match(clientInput, "^[/:]{1}").Success&& commandingClient.isAdmin) { commandingClient.outgoing.WriteLine("You typed an admin command indicator (/,:)."); commandingClient.outgoing.WriteLine("These commands are not yet implemented."); }//if (clientInput.IndexOf(" ") != -1) // Three ways I can see to do this: These two and a regex. What would be the least resource-intensive? else if (clientInput.Contains(' ')) // If there's a space, then there are multiple words in the string and the first word might be a command. { parsedCommand = Regex.Match(clientInput, "^\\S*\\b{1}").Value; // Parse the first word out of the string, below we'll compare it against our list of commands to see if it's a valid command. adjustedClientInput = Regex.Replace(clientInput, "^\\S*\\s{1}", string.Empty); // And here's the content of the supposed command. } else { parsedCommand = clientInput.ToLower(); // If there are no spaces, then the input is all one word, and we'll check to see if THAT is a command. // first check to see if the player is trying to exit the room foreach (EXIT exitEnum in commandingClient.currentRoom.exits) { if (exitEnum.exitName.ToLower() == parsedCommand.ToLower()) { RoomHandler.changeRoom(commandingClient, RoomHandler.findRoom(exitEnum.exitDestination)); parsedCommand = "roomchange"; break; } } } //Input method to check the parsed command against any special commands defined by the room the player is currently in. if (adminCommandList.Contains(parsedCommand)) { if (commandingClient.isAdmin) { switch (parsedCommand) // What would be a better method of listing commands? // For admin commands, this needs to check for privilege level. { // Maybe listing the commands in a database table and polling for something that matches the input? case "nuser": NewUser(commandingClient); break; case "laccounts": // List all usernames in the database. In the future I'll add a few flags to these db entries which will be displayed here. ListAccounts(commandingClient); break; case "kick": KickUser(commandingClient, adjustedClientInput); break; case "ban": BanUser(commandingClient, adjustedClientInput); break; case "unban": UnBanUser(commandingClient, adjustedClientInput); break; case "xmltest": RoomHandler.readRoom(commandingClient, "../../TestRoom1.xml"); break; case "loadcheck": commandingClient.outgoing.WriteLine("Reading room data..."); RoomHandler.showLoadedRooms(commandingClient); commandingClient.outgoing.WriteLine("Finished."); break; case "findroom": commandingClient.outgoing.WriteLine("Looking for room: " + adjustedClientInput); commandingClient.outgoing.WriteLine(RoomHandler.findRoom(adjustedClientInput).roomName); break; default: break; } } else { commandingClient.outgoing.WriteLine("\nYou must be an admin to use that command."); } } else // if(commandList.Contains(parsedCommand)) // Can add this in if we want to give the user an error when they give input that is not in the command list, instead of simply treating it like a Say command. { switch (parsedCommand.ToLower()) { case "quit!": commandingClient.disconnectFlag = true; break; case "dog": commandingClient.outgoing.WriteLine("\nYou found the secret word!"); // Because, dammit! break; case "say": ChatServer.Chat(commandingClient, adjustedClientInput, "Say"); break; case "tell": string tellTarget = Regex.Match(adjustedClientInput, "^\\S*\\b{1}").Value; adjustedClientInput = Regex.Replace(adjustedClientInput, "^\\S*\\s{1}", string.Empty); Console.WriteLine(tellTarget + ":" + adjustedClientInput); ChatServer.Tell(commandingClient, tellTarget, adjustedClientInput); break; case "help": commandingClients.Add(commandingClient); OutputHandler.fileOutputHandler("HelpFile.txt", commandingClients); commandingClients.Remove(commandingClient); break; case "chist": DisplayChatHistory(commandingClient); break; case "lusers": ListUsers(commandingClient); break; case "roomchange": break; default: ChatServer.Chat(commandingClient, clientInput, "Say"); // If it's not in the recognized command list, treat it like the clientInput was preceeded by the Say command. break; } } if (!NetworkServer.clientsToDisconnect.Contains(commandingClient)) { commandingClient.outgoing.Write("\nInput Please > "); } } catch (Exception e) { Console.WriteLine(e); LogHandler.LogAClientEvent(e.ToString(), commandingClient); } }
public Client(TcpClient connectedClient) { //*************************************************** // This is here to account for the extra bytes that fat ftp clients (putty, etc) will send upon an initial connection. // Eventually a proper telnet handler will exist and this won't be necessary. //byte[] bytesFromClient = new byte[32]; // Set the buffer size. //var testReader = connectedClient.GetStream().BeginRead(bytesFromClient, 0, bytesFromClient.Length, null, null); // Read all incoming bytes. //WaitHandle waiter = testReader.AsyncWaitHandle; //bool finishedRead = waiter.WaitOne(250, false); // If there are no bytes to read, we'll wait 1/4 of a second before continuing. //if (finishedRead) //{ // connectedClient.GetStream().EndRead(testReader); // foreach (int i in bytesFromClient) // Console.WriteLine("Read a byte:" + i); // This is for debugging. //} //else //{ // connectedClient.GetStream().EndRead(testReader); //} //*************************************************** // Need to add a unique ID, possibly based on yearmonthdayhourminutesecondincrement pattern. This will be a session-unique ID, // but we also need an account-specific identifier. this.isAdmin = false; this.connectedOn = DateTime.Now; // When the client connected. this.disconnectFlag = false; this.loggedInFlag = false; this.clientUsername = "******"; this.connectedClient = connectedClient; this.clientIP = IPAddress.Parse(((IPEndPoint)connectedClient.Client.RemoteEndPoint).Address.ToString()); this.clientEndPoint = connectedClient.Client.RemoteEndPoint; NetworkServer.clientsToLogIn.Add(this); Console.WriteLine("Client connected from: " + clientIP); this.daStream = connectedClient.GetStream(); this.incoming = new StreamReader(daStream); this.outgoing = new StreamWriter(daStream); this.outgoing.AutoFlush = true; // Why? //this.daStream.ReadTimeout = 250; try { this.outgoing.Write("Press any key..."); this.incoming.ReadLine(); } catch (Exception e) { Console.WriteLine(e); } //this.daStream.ReadTimeout = -1; InputHandler.DisplayTextFile(this, "WelcomeScreen.txt"); // Display the welcome screen when the client connects. // Also need a mechanic for creating accounts while (!GateKeeper(this)) { } this.loggedInFlag = true; Console.WriteLine(this.clientUsername + " logged in."); LogHandler.LogAClientEvent("connected", this); // Is it better to put this here or within the GateKeeper? this.outgoing.WriteLine("Welcome " + clientUsername); ChatServer.globalChannel.Add(this); using (SqlConnection dbConnection = new SqlConnection(NetworkServer.connectionString)) // Move this to a method? { dbConnection.Open(); SqlDataReader dbReader = null; SqlCommand dbCommand = new SqlCommand("select lastRoom from users where username like '" + clientUsername + "'", dbConnection); dbReader = dbCommand.ExecuteReader(); dbReader.Read(); string roomToFindInArrayList = dbReader["lastRoom"].ToString(); lastRoom = RoomHandler.findRoom(roomToFindInArrayList); if (lastRoom == null) { lastRoom = RoomHandler.findRoom("TestRoom1"); } } onRoomChange(this, lastRoom); // Make the client appear in the room there were in when they logged off. this.outgoing.Write("\nInput Please > "); }
static void Main(string[] args) // Not sure if I want to take arguments yet, but keeping it here to remind myself { serverStarted = DateTime.Now; LogHandler.CheckForLogFile(); LogHandler.LogServerStart(); CheckForConfigFile(); // This is for future use. RoomHandler.loadAllRooms(); IPAddress myip = Dns.GetHostAddresses("localhost")[0]; // I want it to give me the ipv4 addy, or maybe I'm having a problem using telnet to connect to an ipv6 addy? IPAddress mystaticipv4 = IPAddress.Parse("192.168.1.128"); // V V V This is such an effing pain. V V V receptionist = new TcpListener(mystaticipv4, 7022); // TcpListener(int port) will allow clients to connect to the server's ipv4 addy, but that method is considered 'deprecated' by visual studio :( // TCPListener(int port) will accept connections to any ip addy on the server receptionist.Start(); Console.WriteLine("The receptionist is in. Lines are open at {0}, on port 7022.", myip); // Is it IPv6 notation because I'm using Windows 7? while (true) // The main game loop { if (receptionist.Pending()) // The plan is to move this to a parallel thread { TcpClient client = receptionist.AcceptTcpClient(); Thread t = new Thread(() => Client.CreateClient(client)); // Testing the idea of delegating the client creation to a seperate thread: So far, so good. t.Start(); Console.WriteLine("We have a guest. They're in from " + client.Client.RemoteEndPoint); // This is fine for now, but this info should be appended to the client object for tracking purposes, also this should show the unique identifier for the client. } try { foreach (Client dyingClient in clientsToDisconnect) { CloseClientConnection(dyingClient); } clientsToDisconnect.Clear(); foreach (Client loggingInClient in clientsToLogIn) { if (loggingInClient.loggedInFlag == true) { clients.Add(loggingInClient); } } foreach (Client clientToReadWrite in clients) { //Console.WriteLine("In main foreach loop with" + clientToReadWrite.clientUsername); if (clientsToLogIn.Contains(clientToReadWrite)) { clientsToLogIn.Remove(clientToReadWrite); } if (clientToReadWrite.connectedClient.GetStream().DataAvailable) // Is the connected client trying to send us input? { InputHandler.InputInterpreter(clientToReadWrite); } if (clientToReadWrite.disconnectFlag == true) { clientsToDisconnect.Add(clientToReadWrite); } } ; } catch (Exception e) { Console.WriteLine(e); LogHandler.LogAServerEvent(e.ToString()); } } }