public async void Launch() { IsLaunching = true; GreetingVM.IsShown = false; LaunchProcessStarted?.Invoke(); // Check JRE if (_config.JreDir == null) { _windowManager.ShowMessageBox("${JreNotFound}\n${PleaseInstallJre}", "${IntegrityCheck}", MessageBoxButton.OK, MessageBoxImage.Error); _statusVM.Status = LaunchStatus.Failed; return; } _statusVM.GameOutputLog = null; this.ActivateItem(_statusVM); _statusVM.Status = LaunchStatus.LoggingIn; // No account found, the user must create one var account = _accountService.GetSelected(); if (account == null) { _accountEditVM.Setup(AccountEditType.AddAccount); if (_windowManager.ShowDialog(_accountEditVM) != true) { _statusVM.Status = LaunchStatus.Failed; return; } account = _accountService.GetSelected(); } else { // Previous login token is invalid, need re-authentication var authResult = await _authService.LoginAsync(account); if (!authResult.IsSuccessful) { _accountEditVM.Setup(AccountEditType.ReAuth, account); if (_windowManager.ShowDialog(_accountEditVM) != true) { _statusVM.Status = LaunchStatus.Failed; return; } } else if (authResult.SelectedProfile == null) { var selectedProfile = authResult.AvailableProfiles.FirstOrDefault(); _profileSelectVM.Setup(authResult.AvailableProfiles, account.ProfileServer); if (_windowManager.ShowDialog(_profileSelectVM) ?? false) { selectedProfile = _profileSelectVM.SelectedProfile; } account.Username = selectedProfile.Name; account.UUID = selectedProfile.Id; await _accountService.LoadSkinAsync(account); GreetingVM.NotifyAccountChanged(); } } // Check authlib-injector if selected account is using external authentication if (account.AuthMode == AuthMode.AuthLibInjector) { if (!_authlibInjectorService.CheckIntegrity(account.AuthlibInjectorSHA256)) { // Authlib-Injector is missing or damaged var latest = await _authlibInjectorService.GetLatest(); if (latest == null) { _statusVM.Status = LaunchStatus.Failed; return; } var download = _authlibInjectorService.GetDownload(latest); if (!await StartDownloadAsync(DownloadType.AuthlibInjector, download)) { _statusVM.Status = LaunchStatus.Failed; return; } account.AuthlibInjectorSHA256 = latest.SHA256; } account.PrefetchedAuthServerInfo = await _authService.PrefetchAuthServerInfo(account.AuthServerBase); if (account.PrefetchedAuthServerInfo == null) { _statusVM.Status = LaunchStatus.Failed; return; } } _statusVM.Status = LaunchStatus.ProcessingDependencies; var launchVersion = _versionService.GetByID(_config.SelectedVersion); // Check main jar and fix possible damage if (!_versionService.CheckIntegrity(launchVersion)) { var download = _versionService.GetDownload(launchVersion); if (!await StartDownloadAsync(DownloadType.MainJar, download)) { _statusVM.Status = LaunchStatus.Failed; return; } } // Check dependent libraries and fix possible damage var damagedLibs = await _libraryService.CheckIntegrityAsync(launchVersion.Libraries); if (damagedLibs.Any()) { // For 1.13.2+ forge versions, there is no way to fix damaged forge jar unless reinstall if (launchVersion.Type == VersionType.NewForge && damagedLibs.Any( lib => lib.Type == LibraryType.ForgeMain )) { _windowManager.ShowMessageBox("${MainJarDamaged}\n${PleaseReinstallForge}", "${IntegrityCheck}", MessageBoxButton.OK, MessageBoxImage.Error); // Delete the damaged forge version (but retain the libraries) // force user to reinstall it await _versionService.DeleteFromDiskAsync(launchVersion.ID, false); _statusVM.Status = LaunchStatus.Failed; return; } var downloads = _libraryService.GetDownloads(damagedLibs); if (!await StartDownloadAsync(DownloadType.Libraries, downloads)) { _statusVM.Status = LaunchStatus.Failed; return; } } // Extract native libraries _libraryService.ExtractNatives(launchVersion.Libraries.Where(lib => lib.Type == LibraryType.Native)); // Try loading assets if (!_assetService.LoadAllObjects(launchVersion.AssetsInfo)) { if (await _assetService.DownloadIndexJsonAsync(launchVersion.AssetsInfo)) { // Successfully downloaded the missing index json, load assets _assetService.LoadAllObjects(launchVersion.AssetsInfo); } // if index json download failed (what are the odds!), not gonna retry // Prepare for enjoying a silent game XD } // Check assets and fix possible damage on user's discretion var damagedAssets = await _assetService.CheckIntegrityAsync(launchVersion.AssetsInfo); if ((damagedAssets?.Any() ?? false) && _windowManager.ShowMessageBox("${AssetsDamaged}\n${WhetherFixNow}", "${IntegrityCheck}", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) { var downloads = _assetService.GetDownloads(damagedAssets); await StartDownloadAsync(DownloadType.Assets, downloads); } // For legacy versions (1.7.2 or earlier), copy hashed asset objects to virtual files if (launchVersion.AssetsInfo.IsLegacy) { await _assetService.CopyToVirtualAsync(launchVersion.AssetsInfo); } // All good to go, now build launch profile var profile = new LaunchProfile { IsDebugMode = _config.JavaDebugMode, JvmArgs = _config.JvmArgs, MaxMemory = _config.JavaMaxMem, Account = account, VersionType = AssemblyUtil.Title, WinWidth = _config.WindowWidth, WinHeight = _config.WindowHeight, IsFullScreen = _config.FullScreen, ServerAddress = _config.ServerAddress, ExtraArgs = _config.ExtraMinecraftArgs, }; _statusVM.Status = LaunchStatus.StartingProcess; void UpdateLogDisplay(string logMessage) => _statusVM.GameOutputLog = logMessage; _launchService.LogReceived += UpdateLogDisplay; if (!await _launchService.LaunchGameAsync(profile, launchVersion)) { _statusVM.Status = LaunchStatus.Failed; _launchService.LogReceived -= UpdateLogDisplay; return; } _statusVM.Status = LaunchStatus.Running; _launchService.LogReceived -= UpdateLogDisplay; _statusVM.GameOutputLog = XD; }