/// <summary> /// Raises the PlayerParted event. /// </summary> /// <param name="player"></param> protected void OnPlayerParted(ref PlayerProfile player) { PlayerParted?.Invoke(player.Name, player.UUID, player.IP); }
private void RunServer() { bool ServerShutdownSignaled = false; string playerName = ""; string playerUUID = ""; OnServerStarting(); Process proc = new Process { StartInfo = new ProcessStartInfo { FileName = "java", Arguments = "-Xmx" + mvarMemorySize.ToString() + "M -Xms" + mvarMemorySize.ToString() + "M -jar " + mvarServerJar, // + " nogui", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, CreateNoWindow = true, WorkingDirectory = mvarServerPath } }; proc.Start(); while (!proc.StandardOutput.EndOfStream) { string line = proc.StandardOutput.ReadLine(); if (line.IndexOf("]:") > -1) { LogEntry entry = ParseConsoleLine(line); // if: server thread if (entry.LogMessage.Substring(0, entry.LogMessage.IndexOf(' ')).ToLower() == "done" && entry.LogMessage.ToLower().IndexOf("for help, type") > -1) { // Raise the ServerStarted event :D OnServerStarted(); } else if (entry.LogMessage.ToLower() == "stopping the server" || entry.LogMessage.ToLower() == "stopping server") { if (!ServerShutdownSignaled) { // Tell RCon to disconnect, if it's running if (RCon.IsConnected) { RCon.Disconnect(); } // Raise the ServerShuttingDown event OnServerShuttingDown(); // Indicate that we have already completed this event handling ServerShutdownSignaled = true; } } else if (entry.LogMessage.ToLower().IndexOf("logged in with entity id") > -1 && entry.LogMessage.IndexOf('[') > -1 && entry.LogMessage.IndexOf(']') > -1) { if (playerName.Length > 0 && playerUUID.Length > 0) { // PlayerJoinBug //if(entry.LogMessage.IndexOf(playerName) > -1) //{ // // We need to split the IP the player is connecting from... // // Then we need to add this player to the online list // // For reference: // // [06:30:34 INFO]: Mateatdang[/172.30.1.55:61105] logged in with entity id 245 at ([world]4.805233873224047, 4.0, 21.78309565413898) // string ipString = entry.LogMessage.Substring(entry.LogMessage.IndexOf('[') + 1, entry.LogMessage.Length - (entry.LogMessage.IndexOf('[') + 1)); // ipString = ipString.Substring(0, ipString.IndexOf(':')); // // Just in case: remove any leading slash // ipString = ipString.Replace("/", ""); // // Lets see if there's a period inhere // if (ipString.IndexOf('.') > -1) // { // // Split the possible IP string into it's individual parts // string[] ipParts = ipString.Split('.'); // // Convert it into a byte array // byte[] ip = ConvertIP(ipParts); // // Create the player profile... // PlayerProfile player = new PlayerProfile(DateTime.Now, playerName, playerUUID, ip); // // And add it to the current online list // lock (mvarOnlinePlayers) // { // // Ensures that we keep0 synchronized data across threads // mvarOnlinePlayers.Add(player); // } // //NOTE: if needed, add an event that we can raise when a player joins // System.Diagnostics.Debug.WriteLine("### >>> " + player.Name + " has joined the game."); // // Raise the PlayerJoined event // OnPlayerJoined(ref player); // } //} } } else if (entry.LogMessage.ToLower().IndexOf(" lost connection:") > -1) { // [21:01:36 INFO]: Mateatdang lost connection: Server closed string firstWord = entry.LogMessage.Substring(0, entry.LogMessage.IndexOf(' ')); // The first word is supposed to be a player's name // Check to see if there is some kind of formatting there... // Possible json: {"text":"This is raw text"} if ( firstWord.IndexOf('<') + firstWord.IndexOf('>') + firstWord.IndexOf('{') + firstWord.IndexOf('}') + firstWord.IndexOf('[') + firstWord.IndexOf(']') + firstWord.IndexOf(':') + firstWord.IndexOf('\"') == -8) { PlayerProfile player = new PlayerProfile(DateTime.Now, "", "", new byte[] { 0, 0, 0, 0 }); lock (mvarOnlinePlayers) { int playerIndex = -1; for (int p = 0; p < mvarOnlinePlayers.Count; p++) { if (mvarOnlinePlayers[p].Name == firstWord) { playerIndex = p; break; } } if (playerIndex > -1) { player = mvarOnlinePlayers[playerIndex]; mvarOnlinePlayers.RemoveAt(playerIndex); //NOTE: we could add an event that can be raised when a player disconnects System.Diagnostics.Debug.WriteLine("### >>> " + firstWord + " has left the game."); } } // Did we find the player that disconnected? if (player.Name.Length > 0 && player.UUID.Length > 0) { // Yes we did, so raise the event! OnPlayerParted(ref player); } } } else if (entry.LogMessage.ToLower().IndexOf("라이센스가 만료되었습니다.") > -1) { if (!ServerShutdownSignaled) { // Tell RCon to disconnect, if it's running if (RCon.IsConnected) { RCon.Disconnect(); } showLicenseExpiredDialog(); proc.Kill(); OnServerShuttingDown(); // Indicate that we have already completed this event handling ServerShutdownSignaled = true; } } // Force the playerName and playerUUID variables empty playerName = ""; playerUUID = ""; // By forcing these two variables to alway be empty here, // we effectively prevent players from being able to cheat the parse // into believing a player has joined. // else if: the rcon listener thread - can't remember the output :P if (entry.LogMessage.ToLower().IndexOf("rcon running on") > -1) { string portInfo = entry.LogMessage.Substring(entry.LogMessage.LastIndexOf(':') + 1, entry.LogMessage.Length - (entry.LogMessage.LastIndexOf(':') + 1)); int port = FixInt(portInfo); // Is the console log shown port identical to our configured port? if (port == mvarRemoteConsolePort) { // We can now safely assume the server is listening for rcon connections! // So ... start the rcon RCon.Connect(new byte[] { 127, 0, 0, 1 }, mvarRemoteConsolePort, RConPassword); } } // else if: User Authenticator // We know that we can expect to get: // The player's name (the current name) // The UUID of the player's account (Mojang Account!) // Sample of Login: // [06:30:33 INFO]: UUID of player Mateatdang is 4c1db48f-4d2c-3efa-bd22-b28f56df0ce3 if (entry.LogMessage.ToLower().IndexOf("uuid of player") > -1 && entry.LogMessage.ToLower().IndexOf(" is ") > -1) { playerUUID = entry.LogMessage.Substring(entry.LogMessage.LastIndexOf(' ') + 1, entry.LogMessage.Length - (entry.LogMessage.LastIndexOf(' ') + 1)); playerName = entry.LogMessage.Substring(0, entry.LogMessage.LastIndexOf(" is ")); playerName = playerName.Substring(playerName.LastIndexOf(' ') + 1, playerName.Length - (playerName.LastIndexOf(' ') + 1)); // Temp IP address byte[] ip = new byte[] { 0, 0, 0, 0 }; // Create the player profile... PlayerProfile player = new PlayerProfile(DateTime.Now, playerName, playerUUID, ip); // And add it to the current online list lock (mvarOnlinePlayers) { // Ensures that we keep0 synchronized data across threads mvarOnlinePlayers.Add(player); } //NOTE: if needed, add an event that we can raise when a player joins System.Diagnostics.Debug.WriteLine("### >>> " + player.Name + " has joined the game."); // Raise the PlayerJoined event OnPlayerJoined(ref player); } //NOTE: We can also add in a connection counter, based on the source: [User Authenticator #1] // Simple thing to do: cut away "user authenticator" and convert to int - expose as property, job done! :) OnConsoleChanged(entry.LogLevel, line); } } proc.WaitForExit(); proc.Dispose(); // Clean up the server.properties after run has completed UpdateServerProperties(false); mvarOnlinePlayers.Clear(); OnServerStopped(); }