/// <summary>
        /// Starts the Battlefield 2 Server application
        /// </summary>
        /// <param name="Mod">The battlefield 2 mod that the server is to use</param>
        /// <param name="ExtraArgs">Any arguments to be past to the application on startup</param>
        public static void Start(BF2Mod Mod, string ExtraArgs)
        {
            // Make sure the server isnt running already
            if (IsRunning)
            {
                throw new Exception("Battlefield 2 is already running!");
            }

            // Make sure the mod is supported!
            if (!Mods.Contains(Mod))
            {
                throw new Exception("The battlefield 2 mod cannot be located in the mods folder");
            }

            // Start new BF2 proccess
            ProcessStartInfo Info = new ProcessStartInfo();

            Info.Arguments = String.Format(" +modPath mods/{0}", Mod.Name.ToLower());
            if (!String.IsNullOrEmpty(ExtraArgs))
            {
                Info.Arguments += " " + ExtraArgs;
            }

            // Start process. Set working directory so we dont get errors!
            Info.FileName         = "bf2.exe";
            Info.WorkingDirectory = RootPath;
            ClientProcess         = Process.Start(Info);

            // Hook into the proccess so we know when its running, and register a closing event
            ClientProcess.EnableRaisingEvents = true;
            ClientProcess.Exited += ServerProcess_Exited;

            // Call event
            if (Started != null)
            {
                Started();
            }

            while (!ClientProcess.WaitForInputIdle(50))
            {
                Application.DoEvents();
            }
        }
        /// <summary>
        /// Loads a battlefield 2 server into this object for use.
        /// </summary>
        /// <param name="Bf2Path">The full root path to the server's executable file</param>
        public static void SetInstallPath(string Bf2Path)
        {
            // Write trace
            TraceLog.WriteLine($"Loading Battlefield 2 directory: \"{Bf2Path}\"");
            TraceLog.Indent();

            // Make sure we have a valid server path
            if (!File.Exists(Path.Combine(Bf2Path, "bf2.exe")))
            {
                // Write trace
                TraceLog.TraceError("Invalid BF2 installation path. bf2.exe does not exist!");
                TraceLog.Unindent();
                throw new ArgumentException("Invalid BF2 installation path");
            }

            // Make sure we actually changed server paths before processing
            if (!String.IsNullOrEmpty(RootPath) && (new Uri(Bf2Path)) == (new Uri(RootPath)))
            {
                // Write trace
                TraceLog.WriteLine("Installation directory was not changed, aborting.");
                TraceLog.Unindent();

                // Same path is selected, just return
                return;
            }

            // Temporary variables
            string        Modpath  = Path.Combine(Bf2Path, "mods");
            List <BF2Mod> TempMods = new List <BF2Mod>();

            // Make sure the server has the required folders
            if (!Directory.Exists(Modpath))
            {
                // Write trace
                TraceLog.TraceError("Unable to locate the 'mods' folder.");
                TraceLog.Unindent();
                throw new Exception("Unable to locate the 'mods' folder. Please make sure you have selected a valid "
                                    + "battlefield 2 installation path before proceeding.");
            }

            // Load all found mods, discarding invalid mods
            ModLoadErrors = new List <string>();
            IEnumerable <string> ModList = from dir in Directory.GetDirectories(Modpath) select dir.Substring(Modpath.Length + 1);

            foreach (string Name in ModList)
            {
                try
                {
                    // Create a new instance of the mod, and store it for later
                    BF2Mod Mod = new BF2Mod(Modpath, Name);
                    TempMods.Add(Mod);
                    TraceLog.WriteLine("Loaded mod: " + Mod.Name);
                }
                catch (InvalidModException E)
                {
                    ModLoadErrors.Add(E.Message);
                    TraceLog.WriteLine($"Failed to Load mod: \"{Name}\" Error: {E.Message}");
                    continue;
                }
                catch (Exception E)
                {
                    ModLoadErrors.Add(E.Message);
                    TraceLog.TraceError($"Caught Exception loading mod: \"{Name}");
                    TraceLog.Indent();
                    TraceLog.WriteLine(E.Message);
                    TraceLog.Unindent();
                }
            }

            // We need mods bro...
            if (TempMods.Count == 0)
            {
                TraceLog.TraceError($"No valid mods could be found!");
                throw new Exception("No valid battlefield 2 mods could be found in the Bf2 Server mods folder!");
            }

            // Define var values after we now know this server apears valid
            RootPath = Bf2Path;
            Mods     = TempMods;
            TraceLog.Unindent();

            // Fire change event
            if (PathChanged != null)
            {
                PathChanged();
            }

            // Recheck server process
            CheckServerProcess();
        }
        /// <summary>
        /// Event fired when the Launch Battlefield 2 button is pushed on the Launcher Tab
        /// </summary>
        private async void LaunchButton_Click(object sender, EventArgs args)
        {
            // Lock button to prevent spam
            LaunchButton.Enabled = false;

            // Close the app
            if (BF2Client.IsRunning)
            {
                BF2Client.Stop();
                return;
            }

            // Show overlay first, which provides the smokey (Modal) background
            using (ModalOverlay overlay = new ModalOverlay(this, 0.3))
            {
                // Show overlay
                overlay.Show(this);

                // Make sure a mod is selected
                if (ModComboBox.SelectedIndex < 1)
                {
                    MetroMessageBox.Show(overlay,
                                         "Please select a Bf2 Mod before attempting to start the game!",
                                         "No Mod Selected", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, 150
                                         );
                    overlay.Close();

                    // Reset button
                    BF2Client_Exited();

                    // Focus the mod select
                    ModComboBox.Focus();
                    return;
                }

                // Grab our mod and provider
                BF2Mod          Mod      = ModComboBox.SelectedItem as BF2Mod;
                ServiceProvider Provider = ProviderComboBox.SelectedItem as ServiceProvider;
                Server          Server   = ServerComboBox.SelectedItem as Server;

                // Remove old redirects
                Redirector.RemoveRedirects();

                // If we arent using a provider, skip to just launching the game
                if (Provider == null)
                {
                    goto StartClient;
                }

                // Apply redirects in a new thread
                SyncProgress <TaskStep> MyProgress = new SyncProgress <TaskStep>(RedirectStatusUpdate);
                bool Success = await Redirector.ApplyRedirectsAsync(Provider, MyProgress);

                if (!Success)
                {
                    // Show error
                    MetroMessageBox.Show(overlay, ErrorStep.Description, "Redirect Error", MessageBoxButtons.OK, MessageBoxIcon.Error, 180);
                    overlay.Close();

                    // Reset button
                    BF2Client_Exited();
                    return;
                }

                // Show the Task Form
                TaskForm.Show(this, "Launching Battlefield 2", $"Starting Battlefield 2 with mod \"{Mod.Title}\"", false, ProgressBarStyle.Marquee, 0);

                // Our goto to start the game
StartClient:
                {
                    try
                    {
                        // ===
                        // ALWAYS Remove all temporary keys before this next point
                        // ===
                        Params.Reload(LaunchParamsTextBox.Text);
                        Params.ClearTempParams();

                        // If we are auto joining a server, we must login!
                        if (Provider != null && (Server != null || CredentialsCheckBox.Checked))
                        {
                            // Prompt user to login!
                            using (LoginForm f = new LoginForm(Provider))
                            {
                                DialogResult Res = f.ShowDialog(overlay);
                                if (Res == DialogResult.Cancel)
                                {
                                    // Reset button
                                    TaskForm.CloseForm();
                                    BF2Client_Exited();
                                    return;
                                }

                                // Set server params
                                if (Server != null)
                                {
                                    Params.AddOrSet("joinServer", Server.Address);
                                    Params.AddOrSet("port", Server.Port.ToString());
                                }

                                // Set login params
                                Params.AddOrSet("playerName", f.UsernameTextBox.Text);
                                Params.AddOrSet("playerPassword", f.PasswordTextBox.Text);
                            }
                        }

                        // Start the client executable
                        BF2Client.Start(Mod, Params.BuildString(true));
                    }
                    catch (Exception e)
                    {
                        // Show error
                        MetroMessageBox.Show(overlay, e.Message, "Failure to Launch", MessageBoxButtons.OK, MessageBoxIcon.Error, 180);
                        BF2Client_Exited();
                    }
                }

                // Close the task form
                TaskForm.CloseForm();

                // Close Task form and overlay
                using (RunningOverlay = new GameRunningForm(this))
                {
                    RunningOverlay.ShowDialog(overlay);
                }

                // Close Overlay
                overlay.Close();
                LaunchButton.Focus();
            }
        }