public UnixGameRunner(CompatibilityTools compatibility, DalamudLauncher dalamudLauncher, bool dalamudOk, DalamudLoadMethod?loadMethod, DirectoryInfo dotnetRuntime, Storage storage) { this.compatibility = compatibility; this.dalamudLauncher = dalamudLauncher; this.dalamudOk = dalamudOk; this.loadMethod = loadMethod ?? DalamudLoadMethod.DllInject; this.dotnetRuntime = dotnetRuntime; this.storage = storage; }
private void EnableHooksCheckBox_OnChecked(object sender, RoutedEventArgs e) { try { if (!DalamudLauncher.CanRunDalamud(App.Settings.GamePath)) { MessageBox.Show( Loc.Localize("DalamudIncompatible", "The XIVLauncher in-game addon was not yet updated for your current FFXIV version.\nThis is common after patches, so please be patient or ask on the Discord for a status update!"), "XIVLauncher", MessageBoxButton.OK, MessageBoxImage.Asterisk); } } catch (Exception exc) { MessageBox.Show(Loc.Localize("DalamudCompatCheckFailed", "Could not contact the server to get the current compatible FFXIV version for the in-game addon. This might mean that your .NET installation is too old.\nPlease check the Discord for more information.")); Log.Error(exc, "Couldn't check dalamud compatibility."); } }
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 !); }
private void EnableHooksCheckBox_OnChecked(object sender, RoutedEventArgs e) { try { if (!string.IsNullOrEmpty(ViewModel.GamePath) && Util.IsValidFfxivPath(ViewModel.GamePath) && !DalamudLauncher.CanRunDalamud(new DirectoryInfo(ViewModel.GamePath))) { CustomMessageBox.Show( Loc.Localize("DalamudIncompatible", "Dalamud was not yet updated for your current FFXIV version.\nThis is common after patches, so please be patient or ask on the Discord for a status update!"), "XIVLauncher", MessageBoxButton.OK, MessageBoxImage.Asterisk, parentWindow: Window.GetWindow(this)); } } catch (Exception exc) { CustomMessageBox.Show(Loc.Localize("DalamudCompatCheckFailed", "Could not contact the server to get the current compatible FFXIV version Dalamud. This might mean that your .NET installation is too old.\nPlease check the Discord for more information."), "XIVLauncher Problem", MessageBoxButton.OK, MessageBoxImage.Hand, parentWindow: Window.GetWindow(this)); Log.Error(exc, "Couldn't check dalamud compatibility."); } }
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; } }
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(_setting.GamePath, SteamCheckBox.IsChecked == true); } _isLoggingIn = false; return; } #endif var loginResult = _game.Login(LoginUsername.Text, LoginPassword.Password, otp, SteamCheckBox.IsChecked == true, _setting.UniqueIdCacheEnabled, _setting.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(_setting.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, _setting.SteamIntegrationEnabled, SteamCheckBox.IsChecked == true, _setting.AdditionalLaunchArgs, _setting.GamePath, _setting.IsDx11, _setting.Language); if (gameProcess == null) { Log.Information("GameProcess was null..."); _isLoggingIn = false; return; } var addonMgr = new AddonManager(); try { var addons = _setting.AddonList.Where(x => x.IsEnabled).ToList(); try { var backupDirectory = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "XIVLauncher", "charDataBackup")); if (backupDirectory.Exists) { backupDirectory.Delete(true); } addons.Add(new AddonEntry { Addon = new CharacterBackupAddon() }); } catch (Exception ex) { Log.Error(ex, "Could not delete backup directory to start character backup Addon. This addon will be skipped", "Addons"); } if (_setting.CharacterSyncEnabled) { addons.Add(new AddonEntry { Addon = new CharacterSyncAddon() }); } await Task.Run(() => addonMgr.RunAddons(gameProcess, _setting, addons)); } catch (Exception ex) { new ErrorWindow(ex, "This could be caused by your antivirus, please check its logs and add any needed exclusions.", "Addons", _setting).ShowDialog(); _isLoggingIn = false; addonMgr.StopAddons(); } try { if (_setting.InGameAddonEnabled && _setting.IsDx11) { var hooks = new DalamudLauncher(gameProcess); hooks.Run(_setting.GamePath, _setting.Language); } } catch (Exception ex) { new ErrorWindow(ex, "This could be caused by your antivirus, please check its logs and add any needed exclusions.", "Hooks", _setting).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", _setting).ShowDialog(); _isLoggingIn = false; } }
public WindowsGameRunner(DalamudLauncher dalamudLauncher, bool dalamudOk, DalamudLoadMethod loadMethod) { this.dalamudLauncher = dalamudLauncher; this.dalamudOk = dalamudOk; this.loadMethod = loadMethod; }