using System.ComponentModel; using System.IO; using System.Net.Http; using System.Text.Json; using System.Windows; using System.Diagnostics; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using System.Security.Cryptography; using Microsoft.Win32; //all of this code was written in 3 days, so expect it to be all over the fucking place lmao namespace PUBG2017PSLauncher { public partial class MainWindow : Window { static readonly HttpClient client = new HttpClient(); static CancellationTokenSource cancellationToken = new CancellationTokenSource(); static List gameHashes = new List(); static List localGameHashes = new List(); static List filesToUpdate = new List(); static List gameFolders = new List(); static Config config = new Config() { gameInstall = AppContext.BaseDirectory+"GameInstall", startOnBoot = false, startMinimized = false, gameIsInstalled = false, lastPlayed = DateTime.Now, playtime = 0, webServerIp = "https://w3.dev.tlogin.zxwmr.top/resource/files/game/" }; static GameInfo gameInfo = new GameInfo(); static LauncherInfo launcherInfo = new LauncherInfo(); static Process? pubgProcess = null; static DispatcherTimer playtimeTimer = new DispatcherTimer(); static DispatcherTimer updateCheckTimer = new DispatcherTimer(); static readonly string configPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\OGBG\\config.json"; bool inMainPage = true; bool justLaunched = true; bool downloadInProgress = false; bool updateAvailable = false; bool gameIsRunning = false; bool repairInProgress = false; static long totalDownloadSize; static long downloadedAmount; static double downloadSpeed; const int launcherVersion = 3; public MainWindow() { InitializeComponent(); if (!Directory.Exists(Path.GetDirectoryName(configPath))) Directory.CreateDirectory(Path.GetDirectoryName(configPath)); if (!Directory.Exists(AppContext.BaseDirectory + "\\Temp")) Directory.CreateDirectory(AppContext.BaseDirectory + "\\Temp"); if (!File.Exists(configPath)) { File.WriteAllText(configPath, JsonSerializer.Serialize(config)); LoadConfig(); } else LoadConfig(); if (string.IsNullOrEmpty(config.webServerIp)) { config.webServerIp = "https://w3.dev.tlogin.zxwmr.top/resource/files/game/"; } if (!config.startMinimized) { Visibility = Visibility.Visible; ShowInTaskbar = true; } playtimeText.Text = string.Format("{0:F1}", config.playtime/3600f) + " 小时"; lastPlayedText.Text = config.lastPlayed.ToString(); playtimeTimer.Interval = TimeSpan.FromSeconds(1); playtimeTimer.Tick += playtimeTimerTick; updateCheckTimer.Interval = TimeSpan.FromMinutes(2); updateCheckTimer.Tick += updateCheckTimerTick; updateCheckTimer.Start(); if (config.gameIsInstalled && !Directory.EnumerateFileSystemEntries(config.gameInstall).Any()) { config.gameIsInstalled = false; } if(config.gameIsInstalled) { repairGameBtn.IsEnabled = true; uninstallGameBtn.IsEnabled = true; } UpdateInstallButton(); if (!Directory.Exists(config.gameInstall)) Directory.CreateDirectory(config.gameInstall); if (System.Windows.Application.Current.MainWindow.IsInitialized && justLaunched) { try { gameInfo = JsonSerializer.Deserialize(Get($"{config.webServerIp}json/gameinfo.json").Result); gameHashes = JsonSerializer.Deserialize>(Get($"{config.webServerIp}json/hashes.json").Result); gameFolders = JsonSerializer.Deserialize>(Get($"{config.webServerIp}json/folders.json").Result); launcherInfo = JsonSerializer.Deserialize(Get($"{config.webServerIp}json/launcherinfo.json").Result); } catch(Exception ex) { ThrowExceptionMessage(ex); } CheckForLauncherUpdate(); whatsNewText.Text = gameInfo.whatsNew; justLaunched = false; } if (config.gameIsInstalled && File.Exists(config.gameInstall + "\\hashes.json")) { CheckForGameUpdate(); } } private void updateCheckTimerTick(object? sender, EventArgs e) { CheckForGameUpdate(); } void UpdatePage() { if(inMainPage) { mainMenu.Visibility = Visibility.Visible; settingsMenu.Visibility = Visibility.Collapsed; mainBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(33, 33, 33)); mainBtn.Foreground = new SolidColorBrush(Colors.White); settingsBtn.Background = new SolidColorBrush(Colors.Transparent); settingsBtn.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(110, 119, 131)); } else { mainMenu.Visibility = Visibility.Collapsed; settingsMenu.Visibility = Visibility.Visible; mainBtn.Background = new SolidColorBrush(Colors.Transparent); mainBtn.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(110, 119, 131)); settingsBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(33, 33, 33)); settingsBtn.Foreground = new SolidColorBrush(Colors.White); } } void LoadConfig() { config = JsonSerializer.Deserialize(File.ReadAllText(configPath)); gamePathTextBox.Text = config?.gameInstall; startOnBootCheck.IsChecked = config?.startOnBoot; startMinimizedCheck.IsChecked = config?.startMinimized; } void SaveConfig() { config.gameInstall = gamePathTextBox.Text; config.startOnBoot = (bool)startOnBootCheck.IsChecked; config.startMinimized = (bool)startMinimizedCheck.IsChecked; File.WriteAllText(configPath, JsonSerializer.Serialize(config)); } private static async Task Get(string url) { try { var resp = await client.GetAsync(url).ConfigureAwait(false); var content = await resp.Content.ReadAsStringAsync(); // === 调试:打印返回内容 === Debug.WriteLine($"[DEBUG] {url}"); Debug.WriteLine($"[DEBUG] RESP: {content}"); // ============================ return resp.IsSuccessStatusCode ? content : string.Empty; } catch { System.Windows.MessageBox.Show("无法连接服务器,请检查网络。", "OG:BG 启动器", MessageBoxButton.OK, MessageBoxImage.Error); return string.Empty; } } private void Border_MouseDown(object sender, MouseButtonEventArgs e) { if(e.LeftButton == MouseButtonState.Pressed) { this.DragMove(); } } private void closeBtnClick(object sender, RoutedEventArgs e) { System.Windows.Application.Current.Shutdown(); } private void minimizeBtnClick(object sender, RoutedEventArgs e) { WindowState = WindowState.Minimized; } private async void installBtnClick(object sender, RoutedEventArgs e) { if(!config.gameIsInstalled && !downloadInProgress) { downloadInProgress = true; updateCheckTimer.Stop(); gameInstallPathBtn.IsEnabled = false; UpdateInstallButton(); if (!Directory.Exists(config.gameInstall)) Directory.CreateDirectory(config.gameInstall); if (!Directory.Exists(AppContext.BaseDirectory + "\\Temp")) Directory.CreateDirectory(AppContext.BaseDirectory + "\\Temp"); File.WriteAllText(config.gameInstall + "\\hashes.json", JsonSerializer.Serialize(gameHashes)); for(int i = 0; i < gameFolders.Count; i++) { if(!Directory.Exists(config.gameInstall+"\\"+gameFolders[i].path)) Directory.CreateDirectory(config.gameInstall + "\\" + gameFolders[i].path); } totalDownloadSize = 0; GetDownloadSize(gameHashes); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += timerTick; timer.Start(); ToggleDownloadBarVisibility(true); for (int i = 0; i < gameHashes.Count; i++) { if (!cancellationToken.IsCancellationRequested) { Console.WriteLine(gameHashes[i].path); await DownloadFileAsync($"{config.webServerIp}files/{gameHashes[i].path.Replace("\\", "/")}", config.gameInstall + "\\" + gameHashes[i].path, cancellationToken.Token); } else { timer.Stop(); updateCheckTimer.Start(); ToggleDownloadBarVisibility(false); downloadedAmount = 0; totalDownloadSize = 0; downloadSpeed = 0; downloadInProgress = false; gameInstallPathBtn.IsEnabled = true; UpdateInstallButton(); Directory.Delete(config.gameInstall, true); cancellationToken = new CancellationTokenSource(); return; } } ToggleDownloadBarVisibility(false); updateCheckTimer.Start(); config.gameIsInstalled = true; uninstallGameBtn.IsEnabled = true; repairGameBtn.IsEnabled = true; gameInstallPathBtn.IsEnabled = true; downloadInProgress = false; UpdateInstallButton(); } if(downloadInProgress) { cancellationToken.Cancel(); } if (config.gameIsInstalled && !updateAvailable && !gameIsRunning) { try { pubgProcess = new Process(); pubgProcess.StartInfo.FileName = config.gameInstall + "\\" + gameInfo.startupExecutable; pubgProcess.StartInfo.Arguments = gameInfo.startupArgs; pubgProcess.Start(); gameIsRunning = true; pubgProcess.EnableRaisingEvents = true; pubgProcess.Exited += PubgProcessEnded; playtimeTimer.Start(); } catch(Exception ex) { ThrowExceptionMessage(ex, "游戏已崩溃!这通常可能由于你修改了游戏的某些文件,建议尝试修复游戏文件重试!"); } config.lastPlayed = DateTime.Now; lastPlayedText.Text = DateTime.Now.ToString(); uninstallGameBtn.IsEnabled = false; repairGameBtn.IsEnabled = false; gameInstallPathBtn.IsEnabled = false; UpdateInstallButton(); return; } if (gameIsRunning && !pubgProcess.HasExited) { DialogResult result = System.Windows.Forms.MessageBox.Show("你确定吗?", "OG:BG 启动器", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if(result == System.Windows.Forms.DialogResult.Yes) { try { pubgProcess.Kill(); } catch(Exception ex) { Console.WriteLine(ex.Message); } } } if(updateAvailable & !downloadInProgress) { downloadInProgress = true; uninstallGameBtn.IsEnabled = false; repairGameBtn.IsEnabled = false; gameInstallPathBtn.IsEnabled = false; UpdateInstallButton(); GetDownloadSize(filesToUpdate); if (!Directory.Exists(AppContext.BaseDirectory + "\\Temp")) Directory.CreateDirectory(AppContext.BaseDirectory + "\\Temp"); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += timerTick; timer.Start(); ToggleDownloadBarVisibility(true); for (int i = 0; i < filesToUpdate.Count; i++) { if(!cancellationToken.IsCancellationRequested) { Console.WriteLine($"正在更新: {filesToUpdate[i].path}"); await DownloadFileAsync($"{config.webServerIp}files/{filesToUpdate[i].path.Replace("\\", "/")}", config.gameInstall + "\\" + filesToUpdate[i].path, cancellationToken.Token); filesToUpdate.Remove(filesToUpdate[i]); } else { timer.Stop(); ToggleDownloadBarVisibility(false); downloadedAmount = 0; totalDownloadSize = 0; downloadSpeed = 0; downloadInProgress = false; uninstallGameBtn.IsEnabled = true; repairGameBtn.IsEnabled = true; gameInstallPathBtn.IsEnabled = true; UpdateInstallButton(); cancellationToken = new CancellationTokenSource(); return; } } timer.Stop(); ToggleDownloadBarVisibility(false); downloadInProgress = false; updateAvailable = false; downloadedAmount = 0; downloadSpeed = 0; totalDownloadSize = 0; uninstallGameBtn.IsEnabled = true; repairGameBtn.IsEnabled = true; gameInstallPathBtn.IsEnabled = true; File.WriteAllText(config.gameInstall + "\\hashes.json", JsonSerializer.Serialize(gameHashes)); UpdateInstallButton(); return; } } private void playtimeTimerTick(object? sender, EventArgs e) { config.playtime++; playtimeText.Text = string.Format("{0:F1}", config.playtime/3600f) + " 小时"; } //prepare to see a function with the most for loops :) private async void repairGame(object sender, RoutedEventArgs e) { repairInProgress = true; string[] files = Array.Empty(); try { files = Directory.GetFiles(config.gameInstall, "*.*", SearchOption.AllDirectories); } catch(Exception ex) { ThrowExceptionMessage(ex); } List installedFiles = new List(); List installedFilesPaths = new List(); List filesToRepair = new List(); List filesToCheck = new List(); installBtn.IsEnabled = false; repairGameBtn.IsEnabled = false; uninstallGameBtn.IsEnabled = false; UpdateInstallButton(); ToggleDownloadBarVisibility(true); downloadText.Text = "校验文件中..."; for(int i = 0; i < files.Length; i++) { var relativePath = Path.GetRelativePath(config.gameInstall, files[i]); Console.WriteLine($"获取 MD5 哈希值: {relativePath}"); installedFiles.Add(new FileHash() { path = relativePath, hash = await GetMD5(files[i])}); downloadProgress.Value = (i*1d) / (files.Length*1d) * 100; } for(int i = 0; i < installedFiles.Count; i++) { if(installedFiles[i].path == "hashes.json") { installedFiles.Remove(installedFiles[i]); //fuck you hashes, yall dont belong here >:( break; } } downloadText.Text = "扫描损坏/丢失文件..."; for (int i = 0; i < installedFiles.Count; i++) { installedFilesPaths.Add(installedFiles[i].path); } for(int i = 0; i < gameHashes.Count; i++) { if(!installedFilesPaths.Contains(gameHashes[i].path)) { Console.WriteLine($"丢失文件: {gameHashes[i].path}"); filesToRepair.Add(gameHashes[i]); } } filesToCheck = gameHashes; for(int i = 0; i < filesToRepair.Count; i++) { filesToCheck.Remove(filesToRepair[i]); } for (int i = 0; i < filesToCheck.Count; i++) { if (filesToCheck[i].hash != installedFiles[i].hash) { Console.WriteLine($"{filesToCheck[i].path} is borked"); filesToRepair.Add(filesToCheck[i]); } } if(filesToRepair.Count == 0) { System.Windows.MessageBox.Show("所有文件均已校验成功!", "OG:BG 启动器", MessageBoxButton.OK, MessageBoxImage.Information); } else { downloadInProgress = true; if (!Directory.Exists(AppContext.BaseDirectory + "\\Temp")) Directory.CreateDirectory(AppContext.BaseDirectory + "\\Temp"); GetDownloadSize(filesToRepair); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += timerTick; timer.Start(); for (int i = 0; i < filesToRepair.Count; i++) { await DownloadFileAsync($"{config.webServerIp}files/{filesToRepair[i].path.Replace("\\", "/")}", config.gameInstall + "\\" + filesToRepair[i].path, cancellationToken.Token); } timer.Stop(); } ToggleDownloadBarVisibility(false); downloadInProgress = false; repairInProgress = false; downloadedAmount = 0; downloadSpeed = 0; totalDownloadSize = 0; installBtn.IsEnabled = true; repairGameBtn.IsEnabled = true; uninstallGameBtn.IsEnabled = true; UpdateInstallButton(); } private void uninstallGame(object sender, RoutedEventArgs e) { DialogResult result = System.Windows.Forms.MessageBox.Show("你确定吗?", "OG:BG 启动器", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if(result == System.Windows.Forms.DialogResult.Yes) { try { Directory.Delete(config.gameInstall, true); } catch(Exception ex) { ThrowExceptionMessage(ex); } config.gameIsInstalled = false; uninstallGameBtn.IsEnabled = false; repairGameBtn.IsEnabled = false; UpdateInstallButton(); } } private async void CheckForGameUpdate() { gameHashes = JsonSerializer.Deserialize>(await Get($"{config.webServerIp}json/hashes.json")); localGameHashes = JsonSerializer.Deserialize>(File.ReadAllText(config.gameInstall + "\\hashes.json")); for (int i = 0; i < gameHashes.Count; i++) { if (File.Exists(config.gameInstall + "\\" + gameHashes[i].path)) { if (gameHashes[i].hash != localGameHashes[i].hash) { filesToUpdate.Add(gameHashes[i]); } } else { filesToUpdate.Add(gameHashes[i]); } } if (filesToUpdate.Any()) { updateAvailable = true; UpdateInstallButton(); } } private async Task DownloadFileAsync(string url, string filename, CancellationToken token) { try { var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); if (File.Exists(AppContext.BaseDirectory + "\\Temp\\" + Path.GetFileName(filename))) File.Delete(AppContext.BaseDirectory + "\\Temp\\" + Path.GetFileName(filename)); if (!response.IsSuccessStatusCode) { throw new Exception(string.Format("尝试请求,服务器 HTTP 返回 {0}", response.StatusCode)); } var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L; var canReportProgress = total != -1; using (var stream = await response.Content.ReadAsStreamAsync()) { var buffer = new byte[4096]; var isMoreToRead = true; do { var read = await stream.ReadAsync(buffer, 0, buffer.Length, token); if (read == 0) { isMoreToRead = false; } else { var data = new byte[read]; buffer.ToList().CopyTo(0, data, 0, read); using (var fs = new FileStream(AppContext.BaseDirectory+"\\Temp\\"+Path.GetFileName(filename), FileMode.Append)) { await fs.WriteAsync(data, 0, data.Length); } downloadedAmount += read; downloadSpeed += read; if (canReportProgress) { //progress = ((downloadedAmount * 1d) / (totalDownloadSize * 1d) * 100); //downloadText.Text = string.Format("{0:F1}", downloadedAmount / 1073741824f) + "/" + string.Format("{0:F1}", totalDownloadSize / 1073741824f) + " GB (" + string.Format("{0:F1}", downloadSpeed / 1048576f) + " MB/s)"; } } } while (isMoreToRead); } File.Copy(AppContext.BaseDirectory + "\\Temp\\" + Path.GetFileName(filename), filename, true); File.Delete(AppContext.BaseDirectory + "\\Temp\\" + Path.GetFileName(filename)); } catch (TaskCanceledException) when (cancellationToken.IsCancellationRequested) { Console.WriteLine("用户取消请求"); } catch (TaskCanceledException ex) { ThrowExceptionMessage(ex); } catch(Exception ex) { ThrowExceptionMessage(ex); } } private void UpdateInstallButton() { if (downloadInProgress) { installBtnText.Text = "取消安装"; installBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(201, 34, 16)); } else if (config.gameIsInstalled && !gameIsRunning && !updateAvailable && !repairInProgress) { installBtnText.Text = "开始游戏"; installBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(246, 192, 0)); installBtn.Foreground = new SolidColorBrush(Colors.Black); } else if (!downloadInProgress && !config.gameIsInstalled) { installBtnText.Text = "安装游戏"; installBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(246, 192, 0)); installBtn.Foreground = new SolidColorBrush(Colors.Black); } else if (pubgProcess != null) { installBtnText.Text = "停止游戏"; installBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(201, 34, 16)); } else if (updateAvailable && !downloadInProgress && !gameIsRunning) { installBtnText.Text = "更新游戏"; installBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(246, 192, 0)); installBtn.Foreground = new SolidColorBrush(Colors.Black); } else if(repairInProgress) { installBtnText.Text = "..."; installBtn.Background = new SolidColorBrush(System.Windows.Media.Color.FromRgb(48, 48, 48)); installBtn.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(110, 119, 131)); } } private void ToggleDownloadBarVisibility(bool visible) { if(visible) { downloadBar.Visibility = Visibility.Visible; lastPlayed.Visibility = Visibility.Collapsed; playtime.Visibility = Visibility.Collapsed; miscButtons.Visibility = Visibility.Collapsed; } else { downloadBar.Visibility = Visibility.Collapsed; playtime.Visibility = Visibility.Visible; lastPlayed.Visibility = Visibility.Visible; miscButtons.Visibility = Visibility.Visible; } } private void timerTick(object state, EventArgs args) { downloadProgress.Value = (downloadedAmount * 1d) / (totalDownloadSize * 1d) * 100; if(totalDownloadSize >= 1073741824) { downloadText.Text = string.Format("{0:F1}", downloadedAmount / 1073741824f) + "/" + string.Format("{0:F1}", totalDownloadSize / 1073741824f) + " GB (" + string.Format("{0:F1}", downloadSpeed / 1048576d) + " MB/s)"; } else if(totalDownloadSize < 1073741824) { downloadText.Text = string.Format("{0:F1}", downloadedAmount / 1048576f) + "/" + string.Format("{0:F1}", totalDownloadSize / 1048576f) + " MB (" + string.Format("{0:F1}", downloadSpeed / 1048576d) + " MB/s)"; } else if(totalDownloadSize < 1048576) { downloadText.Text = string.Format("{0:F1}", downloadedAmount / 1024f) + "/" + string.Format("{0:F1}", totalDownloadSize / 1024f) + " KB (" + string.Format("{0:F1}", downloadSpeed / 1048576d) + " MB/s)"; } downloadSpeed = 0; } private void PubgProcessEnded(object sender, EventArgs args) { pubgProcess = null; gameIsRunning = false; playtimeTimer.Stop(); config.lastPlayed = DateTime.Now; if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(()=>UpdateInstallButton(), DispatcherPriority.Normal); Dispatcher.Invoke(() => uninstallGameBtn.IsEnabled = true, DispatcherPriority.Normal); Dispatcher.Invoke(() => repairGameBtn.IsEnabled = true, DispatcherPriority.Normal); Dispatcher.Invoke(() => gameInstallPathBtn.IsEnabled = true, DispatcherPriority.Normal); Dispatcher.Invoke(() => lastPlayedText.Text = DateTime.Now.ToString(), DispatcherPriority.Normal); } else { UpdateInstallButton(); lastPlayedText.Text = DateTime.Now.ToString(); uninstallGameBtn.IsEnabled = true; repairGameBtn.IsEnabled = true; gameInstallPathBtn.IsEnabled = true; } } private static void GetDownloadSize(List files) { for (int i = 0; i < files.Count; i++) { totalDownloadSize += files[i].size; } } async void CheckForLauncherUpdate() { if (launcherInfo.version > launcherVersion) { DialogResult result = System.Windows.Forms.MessageBox.Show("已检测到新版本,是否更新?", "OG:BG 启动器", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == System.Windows.Forms.DialogResult.Yes) { totalDownloadSize = launcherInfo.size; ToggleDownloadBarVisibility(true); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += timerTick; timer.Start(); await DownloadFileAsync($"{config.webServerIp}launcher/update.zip", AppContext.BaseDirectory + "\\update.zip", cancellationToken.Token); timer.Stop(); Process.Start(AppContext.BaseDirectory+"Updater\\Updater.exe"); System.Windows.Application.Current.Shutdown(); } } } private void settingsBtnClick(object sender, RoutedEventArgs e) { inMainPage = false; UpdatePage(); } private void startOnBootChecked(object sender, RoutedEventArgs e) { RegistryKey rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); rk.SetValue("OG:BG Launcher", '"' + Process.GetCurrentProcess().MainModule.FileName + '"'); } private void startOnBootUnchecked(object sender, RoutedEventArgs e) { RegistryKey rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); if(rk.GetValueNames().Contains("OG:BG Launcher")) rk.DeleteValue("OG:BG Launcher"); } private void playBtnClick(object sender, RoutedEventArgs e) { inMainPage = true; UpdatePage(); } private void gameInstallBtnClick(object sender, RoutedEventArgs e) { using (var path = new FolderBrowserDialog()) { DialogResult result = path.ShowDialog(); if(result == System.Windows.Forms.DialogResult.OK && !Directory.EnumerateFileSystemEntries(path.SelectedPath).Any()) { config.gameInstall = path.SelectedPath; gamePathTextBox.Text = path.SelectedPath; } else if(result == System.Windows.Forms.DialogResult.OK && Directory.EnumerateFileSystemEntries(path.SelectedPath).Any()) { System.Windows.MessageBox.Show("请选择空文件夹!", "OG:BG 启动器", MessageBoxButton.OK, MessageBoxImage.Warning); } } } private void windowIsClosing(object sender, CancelEventArgs e) { SaveConfig(); } static async Task GetMD5(string filename) { using (var md5 = MD5.Create()) { using (var stream = File.OpenRead(filename)) { var hash = await md5.ComputeHashAsync(stream); return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); } } } static void ThrowExceptionMessage(Exception ex, string customMessage = "") { var st = new StackTrace(ex, true); var frame = st.GetFrame(st.FrameCount-1); System.Windows.MessageBox.Show($"第 {frame.GetFileLineNumber()} 行: {frame.GetMethod()}: {ex.Message}"+Environment.NewLine+customMessage, "OG:BG 启动器", MessageBoxButton.OK, MessageBoxImage.Error); } } class FileHash { public string? path { get; set; } public string? hash { get; set; } public long size { get; set; } } class GameInfo { public string? whatsNew { get; set; } public string? startupExecutable { get; set; } public string? startupArgs { get; set; } } class Folder { public string? path { get; set; } } class Config { public string? gameInstall { get; set; } public bool startOnBoot { get; set; } public bool startMinimized { get; set; } public bool gameIsInstalled { get; set; } public DateTime lastPlayed { get; set; } public int playtime { get; set; } public string? webServerIp { get; set; } } class LauncherInfo { public int version { get; set; } public int size { get; set; } } }