public async Task <Process> StartGameAndAddon(Launcher.LoginResult loginResult, bool isSteam, bool forceNoDalamud)
    {
        var dalamudOk = false;

        IDalamudRunner             dalamudRunner;
        IDalamudCompatibilityCheck dalamudCompatCheck;

        switch (Environment.OSVersion.Platform)
        {
        case PlatformID.Win32NT:
            dalamudRunner      = new WindowsDalamudRunner();
            dalamudCompatCheck = new WindowsDalamudCompatibilityCheck();
            break;

        case PlatformID.Unix:
            dalamudRunner      = new UnixDalamudRunner(Program.CompatibilityTools, Program.DotnetRuntime);
            dalamudCompatCheck = new UnixDalamudCompatibilityCheck();
            break;

        default:
            throw new NotImplementedException();
        }

        var dalamudLauncher = new DalamudLauncher(dalamudRunner, Program.DalamudUpdater, App.Settings.DalamudLoadMethod.GetValueOrDefault(DalamudLoadMethod.DllInject),
                                                  App.Settings.GamePath, App.Storage.Root, App.Settings.ClientLanguage ?? ClientLanguage.English, App.Settings.DalamudLoadDelay);

        try
        {
            dalamudCompatCheck.EnsureCompatibility();
        }
        catch (IDalamudCompatibilityCheck.NoRedistsException ex)
        {
            Log.Error(ex, "No Dalamud Redists found");

            throw;

            /*
             * CustomMessageBox.Show(
             *  Loc.Localize("DalamudVc2019RedistError",
             *      "The XIVLauncher in-game addon needs the Microsoft Visual C++ 2015-2019 redistributable to be installed to continue. Please install it from the Microsoft homepage."),
             *  "XIVLauncher", MessageBoxButton.OK, MessageBoxImage.Exclamation, parentWindow: _window);
             */
        }
        catch (IDalamudCompatibilityCheck.ArchitectureNotSupportedException ex)
        {
            Log.Error(ex, "Architecture not supported");

            throw;

            /*
             * CustomMessageBox.Show(
             *  Loc.Localize("DalamudArchError",
             *      "Dalamud cannot run your computer's architecture. Please make sure that you are running a 64-bit version of Windows.\nIf you are using Windows on ARM, please make sure that x64-Emulation is enabled for XIVLauncher."),
             *  "XIVLauncher", MessageBoxButton.OK, MessageBoxImage.Exclamation, parentWindow: _window);
             */
        }

        if (App.Settings.DalamudEnabled.GetValueOrDefault(true) && !forceNoDalamud && App.Settings.IsDx11.GetValueOrDefault(true))
        {
            try
            {
                dalamudOk = dalamudLauncher.HoldForUpdate(App.Settings.GamePath);
            }
            catch (DalamudRunnerException ex)
            {
                Log.Error(ex, "Couldn't ensure Dalamud runner");

                var runnerErrorMessage = Loc.Localize("DalamudRunnerError",
                                                      "Could not launch Dalamud successfully. This might be caused by your antivirus.\nTo prevent this, please add an exception for the folder \"%AppData%\\XIVLauncher\\addons\".");

                throw;

                /*
                 * CustomMessageBox.Builder
                 *              .NewFrom(runnerErrorMessage)
                 *              .WithImage(MessageBoxImage.Error)
                 *              .WithButtons(MessageBoxButton.OK)
                 *              .WithShowHelpLinks()
                 *              .WithParentWindow(_window)
                 *              .Show();
                 */
            }
        }

        IGameRunner runner;

        var gameArgs = App.Settings.AdditionalArgs ?? string.Empty;

        if (Environment.OSVersion.Platform == PlatformID.Win32NT)
        {
            runner = new WindowsGameRunner(dalamudLauncher, dalamudOk, App.Settings.DalamudLoadMethod.GetValueOrDefault(DalamudLoadMethod.DllInject));
        }
        else if (Environment.OSVersion.Platform == PlatformID.Unix)
        {
            if (App.Settings.WineStartupType == WineStartupType.Custom && App.Settings.WineBinaryPath == null)
            {
                throw new Exception("Custom wine binary path wasn't set.");
            }

            var signal   = new ManualResetEvent(false);
            var isFailed = false;

            if (App.Settings.WineStartupType == WineStartupType.Managed)
            {
                var _ = Task.Run(async() =>
                {
                    await Program.CompatibilityTools.EnsureTool().ConfigureAwait(false);
                    Program.CompatibilityTools.EnsureGameFixes(Program.Config.GameConfigPath);
                }).ContinueWith(t =>
                {
                    isFailed = t.IsFaulted || t.IsCanceled;

                    if (isFailed)
                    {
                        Log.Error(t.Exception, "Couldn't ensure compatibility tool");
                    }

                    signal.Set();
                });

                App.StartLoading("Ensuring compatibility tool...");
                signal.WaitOne();
                signal.Dispose();

                if (isFailed)
                {
                    return(null);
                }
            }

            runner = new UnixGameRunner(Program.CompatibilityTools, dalamudLauncher, dalamudOk, App.Settings.DalamudLoadMethod, Program.DotnetRuntime, App.Storage);

            gameArgs += $" UserPath={Program.CompatibilityTools.UnixToWinePath(App.Settings.GameConfigPath.FullName)}";
            gameArgs  = gameArgs.Trim();
        }
        else
        {
            throw new NotImplementedException();
        }

        Hide();

        // We won't do any sanity checks here anymore, since that should be handled in StartLogin
        var launched = App.Launcher.LaunchGame(runner,
                                               loginResult.UniqueId,
                                               loginResult.OauthLogin.Region,
                                               loginResult.OauthLogin.MaxExpansion,
                                               isSteam,
                                               gameArgs,
                                               App.Settings.GamePath,
                                               App.Settings.IsDx11 ?? true,
                                               App.Settings.ClientLanguage.GetValueOrDefault(ClientLanguage.English),
                                               App.Settings.IsEncryptArgs.GetValueOrDefault(true),
                                               App.Settings.DpiAwareness.GetValueOrDefault(DpiAwareness.Unaware));

        if (launched == null)
        {
            Log.Information("GameProcess was null...");
            IsLoggingIn = false;
            return(null);
        }

        // This is a Windows process handle on Windows, a Wine pid on Unix-like systems
        var     gamePid = 0;
        Process?process = null;

        if (Environment.OSVersion.Platform == PlatformID.Win32NT)
        {
            process = launched as Process;
            gamePid = process !.Id;
        }
        else if (Environment.OSVersion.Platform == PlatformID.Unix)
        {
            gamePid = (int)launched;
        }

        var addonMgr = new AddonManager();

        try
        {
            App.Settings.Addons ??= new List <AddonEntry>();

            var addons = App.Settings.Addons.Where(x => x.IsEnabled).Select(x => x.Addon).Cast <IAddon>().ToList();

            addonMgr.RunAddons(gamePid, addons);
        }
        catch (Exception ex)
        {
            /*
             * CustomMessageBox.Builder
             *              .NewFrom(ex, "Addons")
             *              .WithAppendText("\n\n")
             *              .WithAppendText(Loc.Localize("AddonLoadError",
             *                  "This could be caused by your antivirus, please check its logs and add any needed exclusions."))
             *              .WithParentWindow(_window)
             *              .Show();
             */

            IsLoggingIn = false;

            addonMgr.StopAddons();
            throw;
        }

        Log.Debug("Waiting for game to exit");

        if (Environment.OSVersion.Platform == PlatformID.Win32NT)
        {
            await Task.Run(() => process !.WaitForExit()).ConfigureAwait(false);
        }
        else if (Environment.OSVersion.Platform == PlatformID.Unix)
        {
            Int32 unixPid = Program.CompatibilityTools.GetUnixProcessId(gamePid);
            if (unixPid == 0)
            {
                Log.Error("Could not retrive Unix process ID, this feature currently requires a patched wine version");
                while (Program.CompatibilityTools.GetProcessIds("ffxiv_dx11.exe").Contains(gamePid))
                {
                    Thread.Sleep(5000);
                }
            }
            else
            {
                process = Process.GetProcessById(unixPid);
                var handle = process.Handle;
                await Task.Run(() => process !.WaitForExit()).ConfigureAwait(false);
            }

            UnixGameRunner.RunningPids.Remove(gamePid);
        }
        else
        {
            Environment.Exit(0);
            return(null);
        }

        Log.Verbose("Game has exited");

        if (addonMgr.IsRunning)
        {
            addonMgr.StopAddons();
        }

        try
        {
            if (App.Steam.IsValid)
            {
                App.Steam.Shutdown();
            }
        }
        catch (Exception ex)
        {
            Log.Error(ex, "Could not shut down Steam");
        }

        return(process !);
    }
Exemple #2
0
        private async Task StartGameAndAddon(Launcher.LoginResult loginResult, bool gateStatus)
        {
#if !DEBUG
            if (!gateStatus)
            {
                Log.Information("GateStatus is false.");
                MessageBox.Show(
                    Loc.Localize("MaintenanceNotice", "Maintenance seems to be in progress. The game shouldn't be launched."),
                    "XIVLauncher", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                _isLoggingIn = false;

                return;
            }
#endif

            // We won't do any sanity checks here anymore, since that should be handled in StartLogin

            var gameProcess = Launcher.LaunchGame(loginResult.UniqueId, loginResult.OauthLogin.Region,
                                                  loginResult.OauthLogin.MaxExpansion, App.Settings.SteamIntegrationEnabled,
                                                  SteamCheckBox.IsChecked == true, App.Settings.AdditionalLaunchArgs, App.Settings.GamePath, App.Settings.IsDx11, App.Settings.Language.GetValueOrDefault(ClientLanguage.English), App.Settings.EncryptArguments.GetValueOrDefault(false));

            if (gameProcess == null)
            {
                Log.Information("GameProcess was null...");
                _isLoggingIn = false;
                return;
            }

            CleanUp();

            this.Hide();

            var addonMgr = new AddonManager();

            try
            {
                var addons = App.Settings.AddonList.Where(x => x.IsEnabled).Select(x => x.Addon).Cast <IAddon>().ToList();

                if (App.Settings.InGameAddonEnabled && App.Settings.IsDx11)
                {
                    addons.Add(new DalamudLauncher());
                }

                await Task.Run(() => addonMgr.RunAddons(gameProcess, App.Settings, addons));
            }
            catch (Exception ex)
            {
                new ErrorWindow(ex,
                                "This could be caused by your antivirus, please check its logs and add any needed exclusions.",
                                "Addons").ShowDialog();
                _isLoggingIn = false;

                addonMgr.StopAddons();
            }

            var watchThread = new Thread(() =>
            {
                while (!gameProcess.HasExited)
                {
                    gameProcess.Refresh();
                    Thread.Sleep(1);
                }

                Log.Information("Game has exited.");
                addonMgr.StopAddons();

                CleanUp();

                Environment.Exit(0);
            });
            watchThread.Start();

            Log.Debug("Started WatchThread");
        }
        private async void StartGame(string otp)
        {
            Log.Information("StartGame() called");
            try
            {
                var gateStatus = false;
                try
                {
                    gateStatus = await Task.Run(() => _game.GetGateStatus());
                }
                catch
                {
                    // ignored
                }

                #if !DEBUG
                if (!gateStatus)
                {
                    Log.Information("GateStatus is false.");
                    MessageBox.Show(
                        "Square Enix seems to be running maintenance work right now or the login server is unreachable. The game shouldn't be launched.",
                        "Error", MessageBoxButton.OK, MessageBoxImage.Asterisk);
                    _isLoggingIn = false;

                    return;
                }
                #endif

                var gameProcess = _game.Login(LoginUsername.Text, LoginPassword.Password, otp,
                                              Settings.SteamIntegrationEnabled, Settings.AdditionalLaunchArgs, Settings.UniqueIdCacheEnabled);

                if (gameProcess == null)
                {
                    Log.Error("GameProcess was null...");
                    _isLoggingIn = false;
                    return;
                }

                var addonMgr = new AddonManager();

                try
                {
                    await Task.Run(() => addonMgr.RunAddons(gameProcess, Settings.GetAddonList().Where(x => x.IsEnabled).ToList()));
                }
                catch (Exception ex)
                {
                    new ErrorWindow(ex,
                                    "This could be caused by your antivirus, please check its logs and add any needed exclusions.",
                                    "Addons").ShowDialog();
                    _isLoggingIn = false;

                    addonMgr.StopAddons();
                }

                try
                {
                    if (Settings.IsInGameAddonEnabled())
                    {
                        await Task.Run(() =>
                        {
                            var hooks = new HooksAddon(); hooks.Setup(gameProcess); hooks.Run();
                        });
                    }
                }
                catch (Exception ex)
                {
                    new ErrorWindow(ex,
                                    "This could be caused by your antivirus, please check its logs and add any needed exclusions.",
                                    "Hooks").ShowDialog();
                    _isLoggingIn = false;

                    addonMgr.StopAddons();
                }

                this.Close();

                var watchThread = new Thread(() =>
                {
                    while (!gameProcess.HasExited)
                    {
                        gameProcess.Refresh();
                        Thread.Sleep(1);
                    }

                    Log.Information("Game has exited.");
                    addonMgr.StopAddons();
                    Environment.Exit(0);
                });
                watchThread.Start();
            }
            catch (Exception ex)
            {
                new ErrorWindow(ex, "Please also check your login information or try again.", "Login").ShowDialog();
                _isLoggingIn = false;
            }
        }
Exemple #4
0
        private async void StartGame(string otp)
        {
            Log.Information("StartGame() called");
            try
            {
                var gateStatus = false;
                try
                {
                    gateStatus = await Task.Run(() => _game.GetGateStatus());
                }
                catch
                {
                    // ignored
                }

#if !DEBUG
                if (!gateStatus)
                {
                    Log.Information("GateStatus is false.");
                    var startLauncher = MessageBox.Show(
                        "Square Enix seems to be running maintenance work right now. The game shouldn't be launched. Do you want to start the official launcher to check for patches?", "XIVLauncher", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;

                    if (startLauncher)
                    {
                        Util.StartOfficialLauncher(App.Settings.GamePath, SteamCheckBox.IsChecked == true);
                    }

                    _isLoggingIn = false;

                    return;
                }
#endif

                var loginResult = _game.Login(LoginUsername.Text, LoginPassword.Password, otp, SteamCheckBox.IsChecked == true, App.Settings.UniqueIdCacheEnabled, App.Settings.GamePath);

                if (loginResult == null)
                {
                    Log.Information("LoginResult was null...");
                    _isLoggingIn = false;

                    // If this is an autologin, we don't want to stick around after a failed login
                    if (AutoLoginCheckBox.IsChecked == true)
                    {
                        Close();
                        Environment.Exit(0);
                    }

                    return;
                }

                if (loginResult.State != XivGame.LoginState.Ok)
                {
                    var msgBoxResult = MessageBox.Show(
                        "Your game is out of date. Please start the official launcher and update it before trying to log in. Do you want to start the official launcher?",
                        "Out of date", MessageBoxButton.YesNo, MessageBoxImage.Error);

                    if (msgBoxResult == MessageBoxResult.Yes)
                    {
                        Util.StartOfficialLauncher(App.Settings.GamePath, SteamCheckBox.IsChecked == true);
                    }

                    /*
                     * var patcher = new Game.Patch.PatchInstaller(_game, "ffxiv");
                     * //var window = new IntegrityCheckProgressWindow();
                     * var progress = new Progress<PatchDownloadProgress>();
                     * progress.ProgressChanged += (sender, checkProgress) => Log.Verbose("PROGRESS");
                     *
                     * Task.Run(async () => await patcher.DownloadPatchesAsync(loginResult.PendingPatches, loginResult.OauthLogin.SessionId, progress)).ContinueWith(task =>
                     * {
                     *  //window.Dispatcher.Invoke(() => window.Close());
                     *  MessageBox.Show("Download OK");
                     * });
                     */
                    return;
                }

                var gameProcess = XivGame.LaunchGame(loginResult.UniqueId, loginResult.OauthLogin.Region,
                                                     loginResult.OauthLogin.MaxExpansion, App.Settings.SteamIntegrationEnabled,
                                                     SteamCheckBox.IsChecked == true, App.Settings.AdditionalLaunchArgs, App.Settings.GamePath, App.Settings.IsDx11, App.Settings.Language.GetValueOrDefault(ClientLanguage.English), App.Settings.EncryptArguments.GetValueOrDefault(false));

                if (gameProcess == null)
                {
                    Log.Information("GameProcess was null...");
                    _isLoggingIn = false;
                    return;
                }

                this.Hide();

                var addonMgr = new AddonManager();

                try
                {
                    var addons = App.Settings.AddonList.Where(x => x.IsEnabled).Select(x => x.Addon).Cast <IAddon>().ToList();

                    if (App.Settings.InGameAddonEnabled && App.Settings.IsDx11)
                    {
                        addons.Add(new DalamudLauncher());
                    }

                    await Task.Run(() => addonMgr.RunAddons(gameProcess, App.Settings, addons));
                }
                catch (Exception ex)
                {
                    new ErrorWindow(ex,
                                    "This could be caused by your antivirus, please check its logs and add any needed exclusions.",
                                    "Addons").ShowDialog();
                    _isLoggingIn = false;

                    addonMgr.StopAddons();
                }

                var watchThread = new Thread(() =>
                {
                    while (!gameProcess.HasExited)
                    {
                        gameProcess.Refresh();
                        Thread.Sleep(1);
                    }

                    Log.Information("Game has exited.");
                    addonMgr.StopAddons();
                    Environment.Exit(0);
                });
                watchThread.Start();

                this.Close();
            }
            catch (Exception ex)
            {
                new ErrorWindow(ex, "Please also check your login information or try again.", "Login").ShowDialog();
                _isLoggingIn = false;
            }
        }
        private async void StartGame(string otp)
        {
            Log.Information("StartGame() called");
            try
            {
                var gateStatus = false;
                try
                {
                    gateStatus = await Task.Run(() => _game.GetGateStatus());
                }
                catch
                {
                    // ignored
                }

                #if !DEBUG
                if (!gateStatus)
                {
                    Log.Information("GateStatus is false.");
                    MessageBox.Show(
                        "Square Enix seems to be running maintenance work right now or the login server is unreachable. The game shouldn't be launched.",
                        "Error", MessageBoxButton.OK, MessageBoxImage.Asterisk);
                    _isLoggingIn = false;

                    return;
                }
                #endif

                var loginResult = _game.Login(LoginUsername.Text, LoginPassword.Password, otp, SteamCheckBox.IsChecked == true, Settings.UniqueIdCacheEnabled);

                if (loginResult == null)
                {
                    Log.Information("LoginResult was null...");
                    _isLoggingIn = false;
                    return;
                }

                if (loginResult.State == XivGame.LoginState.NeedsPatch)
                {
                    /*
                     * var patcher = new Game.Patch.PatchInstaller(_game, "ffxiv");
                     * //var window = new IntegrityCheckProgressWindow();
                     * var progress = new Progress<PatchDownloadProgress>();
                     * progress.ProgressChanged += (sender, checkProgress) => Log.Verbose("PROGRESS");
                     *
                     * Task.Run(async () => await patcher.DownloadPatchesAsync(loginResult.PendingPatches, loginResult.OauthLogin.SessionId, progress)).ContinueWith(task =>
                     * {
                     *  //window.Dispatcher.Invoke(() => window.Close());
                     *  MessageBox.Show("Download OK");
                     * });
                     */
                    return;
                }

                var gameProcess = XivGame.LaunchGame(loginResult.UniqueId, loginResult.OauthLogin.Region,
                                                     loginResult.OauthLogin.MaxExpansion, Settings.SteamIntegrationEnabled,
                                                     SteamCheckBox.IsChecked == true, Settings.AdditionalLaunchArgs);

                if (gameProcess == null)
                {
                    Log.Information("GameProcess was null...");
                    _isLoggingIn = false;
                    return;
                }

                var addonMgr = new AddonManager();

                try
                {
                    var addons = Settings.GetAddonList().Where(x => x.IsEnabled).ToList();

                    addons.Add(new AddonEntry {
                        Addon = new CharacterBackupAddon()
                    });

                    if (Settings.CharacterSyncEnabled)
                    {
                        addons.Add(new AddonEntry {
                            Addon = new CharacterSyncAddon()
                        });
                    }

                    await Task.Run(() => addonMgr.RunAddons(gameProcess, addons));
                }
                catch (Exception ex)
                {
                    new ErrorWindow(ex,
                                    "This could be caused by your antivirus, please check its logs and add any needed exclusions.",
                                    "Addons").ShowDialog();
                    _isLoggingIn = false;

                    addonMgr.StopAddons();
                }

                try
                {
                    if (Settings.IsInGameAddonEnabled())
                    {
                        var hooks = new DalamudLauncher(gameProcess);
                        hooks.Run();
                    }
                }
                catch (Exception ex)
                {
                    new ErrorWindow(ex,
                                    "This could be caused by your antivirus, please check its logs and add any needed exclusions.",
                                    "Hooks").ShowDialog();
                    _isLoggingIn = false;

                    addonMgr.StopAddons();
                }

                this.Close();

                var watchThread = new Thread(() =>
                {
                    while (!gameProcess.HasExited)
                    {
                        gameProcess.Refresh();
                        Thread.Sleep(1);
                    }

                    Log.Information("Game has exited.");
                    addonMgr.StopAddons();
                    Environment.Exit(0);
                });
                watchThread.Start();
            }
            catch (Exception ex)
            {
                new ErrorWindow(ex, "Please also check your login information or try again.", "Login").ShowDialog();
                _isLoggingIn = false;
            }
        }