From 74f63df43a01b3deeca261152e3f90a3d0776dbb Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Fri, 5 May 2023 08:45:34 +0100 Subject: [PATCH 001/178] Fix typo in ReShade removal notice (#195) mfw https://twitter.com/boxerpizza/status/1650825767553495041 came back to slap me in the face --- Bloxstrap/Bootstrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 9ecfb0d2..5b915ebe 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -849,7 +849,7 @@ public static void MigrateIntegrations() if (File.Exists(injectorLocation)) { App.ShowMessageBox( - "Roblox has now completeted rollout of the new client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been removed from Bloxstrap.\n\n"+ + "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", MessageBoxImage.Warning ); From 1a4ebad370fa09e81e24a9d590da7df0c2f3c03b Mon Sep 17 00:00:00 2001 From: fxe <64731916+fxeP1@users.noreply.github.com> Date: Sat, 6 May 2023 09:47:16 +0100 Subject: [PATCH 002/178] Implement Direct3D10 rendering mode. --- Bloxstrap/Singletons/FastFlagManager.cs | 12 +++++++++--- Bloxstrap/ViewModels/FastFlagsViewModel.cs | 6 +++++- Bloxstrap/Views/Pages/FastFlagsPage.xaml | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index d158752a..4a5b26f2 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -20,6 +20,7 @@ public class FastFlagManager : JsonManager> { { "Automatic", "" }, { "Direct3D 11", "FFlagDebugGraphicsPreferD3D11" }, + { "Direct3D 10", "FFlagDebugGraphicsPreferD3D11FL10" }, { "Vulkan", "FFlagDebugGraphicsPreferVulkan" }, { "OpenGL", "FFlagDebugGraphicsPreferOpenGL" } }; @@ -120,9 +121,14 @@ public override void Load() if (GetValue("DFIntTaskSchedulerTargetFps") is null) SetValue("DFIntTaskSchedulerTargetFps", 9999); - // reshade / exclusive fullscreen requires direct3d 11 to work - if (GetValue(RenderingModes["Direct3D 11"]) != "True" && App.FastFlags.GetValue("FFlagHandleAltEnterFullscreenManually") == "False") - SetRenderingMode("Direct3D 11"); + // exclusive fullscreen requires direct3d 10/11 to work + if (App.FastFlags.GetValue("FFlagHandleAltEnterFullscreenManually") == "False") + { + if (!(App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11") == "True" || App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11FL10") == "True")) + { + SetRenderingMode("Direct3D 11"); + } + } } public override void Save() diff --git a/Bloxstrap/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/ViewModels/FastFlagsViewModel.cs index a60c5a44..6531153e 100644 --- a/Bloxstrap/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/ViewModels/FastFlagsViewModel.cs @@ -53,7 +53,11 @@ public bool ExclusiveFullscreenEnabled if (value) { - App.FastFlags.SetRenderingMode("Direct3D 11"); + if (!(App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11") == "True" || App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11FL10") == "True")) + { + App.FastFlags.SetRenderingMode("Direct3D 11"); + } + OnPropertyChanged(nameof(SelectedRenderingMode)); } } diff --git a/Bloxstrap/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/Views/Pages/FastFlagsPage.xaml index 1f435dc6..50deec3e 100644 --- a/Bloxstrap/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/Views/Pages/FastFlagsPage.xaml @@ -65,7 +65,7 @@ - + From 5b7d52581c4e8332c81cc0735c744b56d05fd1c1 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 7 May 2023 07:52:45 +0100 Subject: [PATCH 003/178] Minor wording change --- Bloxstrap/Views/Pages/FastFlagsPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloxstrap/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/Views/Pages/FastFlagsPage.xaml index 50deec3e..1d9ff6a5 100644 --- a/Bloxstrap/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/Views/Pages/FastFlagsPage.xaml @@ -65,7 +65,7 @@ - + From 39d919811f1ff1914f5cedd370cda4ca6662f0d3 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 9 May 2023 12:21:56 +0100 Subject: [PATCH 004/178] Add support for game message communication (#183) game scripts can print a client message to send messages to bloxstrap, right now only for setting the presence status message is a json string formatted with the properties "command" and "data" that's prefixed with the string "[SendBloxstrapMessage]" example: print('[SendBloxstrapMessage] {"command":"SetPresenceStatus", "data":"hi"}') --- Bloxstrap/Integrations/DiscordRichPresence.cs | 97 ++++++++++++++++--- Bloxstrap/Models/GameMessage.cs | 13 +++ Bloxstrap/RobloxActivity.cs | 36 +++++++ 3 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 Bloxstrap/Models/GameMessage.cs diff --git a/Bloxstrap/Integrations/DiscordRichPresence.cs b/Bloxstrap/Integrations/DiscordRichPresence.cs index 69c10e45..12a733db 100644 --- a/Bloxstrap/Integrations/DiscordRichPresence.cs +++ b/Bloxstrap/Integrations/DiscordRichPresence.cs @@ -6,6 +6,7 @@ using DiscordRPC; using Bloxstrap.Models.RobloxApi; +using Bloxstrap.Models; namespace Bloxstrap.Integrations { @@ -14,6 +15,8 @@ public class DiscordRichPresence : IDisposable private readonly DiscordRpcClient _rpcClient = new("1005469189907173486"); private readonly RobloxActivity _activityWatcher; + private RichPresence? _currentPresence; + private string? _initialStatus; private long _currentUniverseId; private DateTime? _timeStartedUniverse; @@ -21,8 +24,9 @@ public DiscordRichPresence(RobloxActivity activityWatcher) { _activityWatcher = activityWatcher; - _activityWatcher.OnGameJoin += (_, _) => Task.Run(() => SetPresence()); - _activityWatcher.OnGameLeave += (_, _) => Task.Run(() => SetPresence()); + _activityWatcher.OnGameJoin += (_, _) => Task.Run(() => SetCurrentGame()); + _activityWatcher.OnGameLeave += (_, _) => Task.Run(() => SetCurrentGame()); + _activityWatcher.OnGameMessage += (_, message) => OnGameMessage(message); _rpcClient.OnReady += (_, e) => App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Received ready from user {e.User.Username} ({e.User.ID})"); @@ -46,28 +50,77 @@ public DiscordRichPresence(RobloxActivity activityWatcher) _rpcClient.Initialize(); } - public async Task SetPresence() + public void OnGameMessage(GameMessage message) + { + if (message.Command == "SetPresenceStatus") + SetStatus(message.Data); + } + + public void SetStatus(string status) + { + App.Logger.WriteLine($"[DiscordRichPresence::SetStatus] Setting status to '{status}'"); + + if (_currentPresence is null) + { + App.Logger.WriteLine($"[DiscordRichPresence::SetStatus] Presence is not set, aborting"); + return; + } + + if (status.Length > 128) + { + App.Logger.WriteLine($"[DiscordRichPresence::SetStatus] Status cannot be longer than 128 characters, aborting"); + return; + } + + if (_initialStatus is null) + _initialStatus = _currentPresence.State; + + string finalStatus; + + if (string.IsNullOrEmpty(status)) + { + App.Logger.WriteLine($"[DiscordRichPresence::SetStatus] Status is empty, reverting to initial status"); + finalStatus = _initialStatus; + } + else + { + finalStatus = status; + } + + if (_currentPresence.State == finalStatus) + { + App.Logger.WriteLine($"[DiscordRichPresence::SetStatus] Status is unchanged, aborting"); + return; + } + + _currentPresence.State = finalStatus; + UpdatePresence(); + } + + public async Task SetCurrentGame() { if (!_activityWatcher.ActivityInGame) { - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Clearing presence"); - _rpcClient.ClearPresence(); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Not in game, clearing presence"); + _currentPresence = null; + _initialStatus = null; + UpdatePresence(); return true; } string icon = "roblox"; - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Setting presence for Place ID {_activityWatcher.ActivityPlaceId}"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Setting presence for Place ID {_activityWatcher.ActivityPlaceId}"); var universeIdResponse = await Utilities.GetJson($"https://apis.roblox.com/universes/v1/places/{_activityWatcher.ActivityPlaceId}/universe"); if (universeIdResponse is null) { - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Could not get Universe ID!"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Could not get Universe ID!"); return false; } long universeId = universeIdResponse.UniverseId; - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Got Universe ID as {universeId}"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Got Universe ID as {universeId}"); // preserve time spent playing if we're teleporting between places in the same universe if (_timeStartedUniverse is null || !_activityWatcher.ActivityIsTeleport || universeId != _currentUniverseId) @@ -79,22 +132,22 @@ public async Task SetPresence() var gameDetailResponse = await Utilities.GetJson>($"https://games.roblox.com/v1/games?universeIds={universeId}"); if (gameDetailResponse is null || !gameDetailResponse.Data.Any()) { - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Could not get Universe info!"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Could not get Universe info!"); return false; } GameDetailResponse universeDetails = gameDetailResponse.Data.ToArray()[0]; - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Got Universe details"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Got Universe details"); var universeThumbnailResponse = await Utilities.GetJson>($"https://thumbnails.roblox.com/v1/games/icons?universeIds={universeId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false"); if (universeThumbnailResponse is null || !universeThumbnailResponse.Data.Any()) { - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Could not get Universe thumbnail info!"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Could not get Universe thumbnail info!"); } else { icon = universeThumbnailResponse.Data.ToArray()[0].ImageUrl; - App.Logger.WriteLine($"[DiscordRichPresence::SetPresence] Got Universe thumbnail as {icon}"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Got Universe thumbnail as {icon}"); } List + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Bloxstrap/Dialogs/HyperionDialog.xaml.cs b/Bloxstrap/Dialogs/HyperionDialog.xaml.cs new file mode 100644 index 00000000..a8514fcd --- /dev/null +++ b/Bloxstrap/Dialogs/HyperionDialog.xaml.cs @@ -0,0 +1,100 @@ +using System; +using System.Windows; +using System.Windows.Forms; + +using Bloxstrap.Enums; +using Bloxstrap.Extensions; +using Bloxstrap.ViewModels; + +namespace Bloxstrap.Dialogs +{ + /// + /// Interaction logic for HyperionDialog.xaml + /// + public partial class HyperionDialog : IBootstrapperDialog + { + private readonly HyperionDialogViewModel _viewModel; + + public Bootstrapper? Bootstrapper { get; set; } + + #region UI Elements + public string Message + { + get => _viewModel.Message; + set + { + _viewModel.Message = value; + _viewModel.OnPropertyChanged(nameof(_viewModel.Message)); + } + } + + public ProgressBarStyle ProgressStyle + { + get => _viewModel.ProgressIndeterminate ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous; + set + { + _viewModel.ProgressIndeterminate = (value == ProgressBarStyle.Marquee); + _viewModel.OnPropertyChanged(nameof(_viewModel.ProgressIndeterminate)); + } + } + + public int ProgressValue + { + get => _viewModel.ProgressValue; + set + { + _viewModel.ProgressValue = value; + _viewModel.OnPropertyChanged(nameof(_viewModel.ProgressValue)); + } + } + + public bool CancelEnabled + { + get => _viewModel.CancelButtonVisibility == Visibility.Visible; + set + { + _viewModel.CancelButtonVisibility = (value ? Visibility.Visible : Visibility.Collapsed); + _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); + } + } + #endregion + + public HyperionDialog() + { + _viewModel = new HyperionDialogViewModel(this); + DataContext = _viewModel; + InitializeComponent(); + } + + #region IBootstrapperDialog Methods + // Referencing FluentDialog + public void ShowBootstrapper() => this.ShowDialog(); + + public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close); + + public void ShowSuccess(string message) + { + App.ShowMessageBox(message, MessageBoxImage.Information); + App.Terminate(); + } + + public void ShowError(string message) + { + App.ShowMessageBox($"An error occurred while starting Roblox\n\nDetails: {message}", MessageBoxImage.Error); + App.Terminate(Bootstrapper.ERROR_INSTALL_FAILURE); + } + + public void PromptShutdown() + { + MessageBoxResult result = App.ShowMessageBox( + "Roblox is currently running, but needs to close. Would you like close Roblox now?", + MessageBoxImage.Information, + MessageBoxButton.OKCancel + ); + + if (result != MessageBoxResult.OK) + Environment.Exit(Bootstrapper.ERROR_INSTALL_USEREXIT); + } + #endregion + } +} diff --git a/Bloxstrap/Resources/CancelButtonSmall.png b/Bloxstrap/Resources/CancelButtonSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..77e6a393d41fade2c9e02a5c48e80139c5f1cc62 GIT binary patch literal 2663 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 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + private readonly IBootstrapperDialog _dialog; + + public ICommand CancelInstallCommand => new RelayCommand(CancelInstall); + + public string Title => App.Settings.Prop.BootstrapperTitle; + public string Message { get; set; } = "Please wait..."; + public bool ProgressIndeterminate { get; set; } = true; + public int ProgressValue { get; set; } = 0; + + public Visibility CancelButtonVisibility { get; set; } = Visibility.Collapsed; + + public string Version => $"Bloxstrap v{App.Version}"; + + public HyperionDialogViewModel(IBootstrapperDialog dialog) + { + _dialog = dialog; + } + + private void CancelInstall() + { + _dialog.Bootstrapper?.CancelInstall(); + _dialog.CloseBootstrapper(); + } + } +} From 703181b3360a9bf7408cd3207be86dd6fb0939d8 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Tue, 9 May 2023 21:46:15 +0800 Subject: [PATCH 007/178] Fix styling --- Bloxstrap/Dialogs/HyperionDialog.xaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/Dialogs/HyperionDialog.xaml b/Bloxstrap/Dialogs/HyperionDialog.xaml index bc271a43..41b86c1d 100644 --- a/Bloxstrap/Dialogs/HyperionDialog.xaml +++ b/Bloxstrap/Dialogs/HyperionDialog.xaml @@ -20,7 +20,7 @@ - + @@ -28,8 +28,8 @@ - - + + From 26a7dfe5af81026ed274ec6d7558dfef26345ba4 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 10 May 2023 13:41:36 +0100 Subject: [PATCH 008/178] Make Hyperion dialog inherit from Fluent dialog --- Bloxstrap/ViewModels/FluentDialogViewModel.cs | 10 ++--- .../ViewModels/HyperionDialogViewModel.cs | 37 ++----------------- 2 files changed, 6 insertions(+), 41 deletions(-) diff --git a/Bloxstrap/ViewModels/FluentDialogViewModel.cs b/Bloxstrap/ViewModels/FluentDialogViewModel.cs index fc81ba17..881c4d4b 100644 --- a/Bloxstrap/ViewModels/FluentDialogViewModel.cs +++ b/Bloxstrap/ViewModels/FluentDialogViewModel.cs @@ -1,15 +1,11 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel; using System.Windows; using System.Windows.Input; using System.Windows.Media; + using CommunityToolkit.Mvvm.Input; + using Bloxstrap.Dialogs; -using Bloxstrap.Enums; using Bloxstrap.Extensions; namespace Bloxstrap.ViewModels diff --git a/Bloxstrap/ViewModels/HyperionDialogViewModel.cs b/Bloxstrap/ViewModels/HyperionDialogViewModel.cs index 6a5c452c..c8415f22 100644 --- a/Bloxstrap/ViewModels/HyperionDialogViewModel.cs +++ b/Bloxstrap/ViewModels/HyperionDialogViewModel.cs @@ -1,45 +1,14 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using System.Windows.Media; -using CommunityToolkit.Mvvm.Input; +using System.ComponentModel; using Bloxstrap.Dialogs; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; namespace Bloxstrap.ViewModels { - public class HyperionDialogViewModel : INotifyPropertyChanged + public class HyperionDialogViewModel : FluentDialogViewModel, INotifyPropertyChanged { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private readonly IBootstrapperDialog _dialog; - - public ICommand CancelInstallCommand => new RelayCommand(CancelInstall); - - public string Title => App.Settings.Prop.BootstrapperTitle; - public string Message { get; set; } = "Please wait..."; - public bool ProgressIndeterminate { get; set; } = true; - public int ProgressValue { get; set; } = 0; - - public Visibility CancelButtonVisibility { get; set; } = Visibility.Collapsed; - public string Version => $"Bloxstrap v{App.Version}"; - public HyperionDialogViewModel(IBootstrapperDialog dialog) - { - _dialog = dialog; - } - - private void CancelInstall() + public HyperionDialogViewModel(IBootstrapperDialog dialog) : base(dialog) { - _dialog.Bootstrapper?.CancelInstall(); - _dialog.CloseBootstrapper(); } } } From 3f6154cf84b2bdd8970a111cbbe2208a7813ac62 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 10 May 2023 13:44:09 +0100 Subject: [PATCH 009/178] Change ordering in Appearance menu --- Bloxstrap/ViewModels/AppearanceViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloxstrap/ViewModels/AppearanceViewModel.cs b/Bloxstrap/ViewModels/AppearanceViewModel.cs index b6efcbdf..7e0a4699 100644 --- a/Bloxstrap/ViewModels/AppearanceViewModel.cs +++ b/Bloxstrap/ViewModels/AppearanceViewModel.cs @@ -71,11 +71,11 @@ public string Theme public IReadOnlyDictionary Dialogs { get; set; } = new Dictionary() { { "Fluent", BootstrapperStyle.FluentDialog }, - { "Hyperion", BootstrapperStyle.HyperionDialog }, { "Progress (~2014)", BootstrapperStyle.ProgressDialog }, { "Legacy (2011 - 2014)", BootstrapperStyle.LegacyDialog2011 }, { "Legacy (2009 - 2011)", BootstrapperStyle.LegacyDialog2009 }, { "Vista (2009 - 2011)", BootstrapperStyle.VistaDialog }, + { "Hyperion (2022 - Fake)", BootstrapperStyle.HyperionDialog }, }; public string Dialog From 6de96bbf609ede3e40923711ee92cf4eb0c32745 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Thu, 11 May 2023 00:56:13 +0800 Subject: [PATCH 010/178] Embedding SVG data into dialog and make it theme-aware --- Bloxstrap/Bloxstrap.csproj | 2 -- Bloxstrap/Dialogs/HyperionDialog.xaml | 34 +++++++++++------- Bloxstrap/Dialogs/HyperionDialog.xaml.cs | 11 ++++++ Bloxstrap/Resources/CancelButtonSmall.png | Bin 2663 -> 0 bytes Bloxstrap/Resources/WordmarkRoblox.png | Bin 6104 -> 0 bytes .../ViewModels/HyperionDialogViewModel.cs | 9 ++++- 6 files changed, 40 insertions(+), 16 deletions(-) delete mode 100644 Bloxstrap/Resources/CancelButtonSmall.png delete mode 100644 Bloxstrap/Resources/WordmarkRoblox.png diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 16faf366..05de60f8 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -14,8 +14,6 @@ - - diff --git a/Bloxstrap/Dialogs/HyperionDialog.xaml b/Bloxstrap/Dialogs/HyperionDialog.xaml index 41b86c1d..f0677e10 100644 --- a/Bloxstrap/Dialogs/HyperionDialog.xaml +++ b/Bloxstrap/Dialogs/HyperionDialog.xaml @@ -12,25 +12,33 @@ WindowStartupLocation="CenterScreen" AllowsTransparency="True" Background="Transparent"> - - - - - - - + + + + + + + + + + + + - - + + + \ No newline at end of file diff --git a/Bloxstrap/Dialogs/HyperionDialog.xaml.cs b/Bloxstrap/Dialogs/HyperionDialog.xaml.cs index a8514fcd..feee3528 100644 --- a/Bloxstrap/Dialogs/HyperionDialog.xaml.cs +++ b/Bloxstrap/Dialogs/HyperionDialog.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Windows; using System.Windows.Forms; +using System.Windows.Media; using Bloxstrap.Enums; using Bloxstrap.Extensions; @@ -62,7 +63,17 @@ public bool CancelEnabled public HyperionDialog() { _viewModel = new HyperionDialogViewModel(this); + if (App.Settings.Prop.Theme.GetFinal() == Theme.Light) + { + // Matching the roblox website light theme as close as possible. + _viewModel.DialogBorder = new Thickness(1); + _viewModel.Background = new SolidColorBrush(Color.FromRgb(242, 244, 245)); + _viewModel.Foreground = new SolidColorBrush(Color.FromRgb(57, 59, 61)); + _viewModel.IconColor = new SolidColorBrush(Color.FromRgb(57, 59, 61)); + _viewModel.ProgressBarBackground = new SolidColorBrush(Color.FromRgb(189, 190, 190)); + } DataContext = _viewModel; + InitializeComponent(); } diff --git a/Bloxstrap/Resources/CancelButtonSmall.png b/Bloxstrap/Resources/CancelButtonSmall.png deleted file mode 100644 index 77e6a393d41fade2c9e02a5c48e80139c5f1cc62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2663 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 $"Bloxstrap v{App.Version}"; - + // Using dark theme for default values. + public Thickness DialogBorder { get; set; } = new Thickness(0); + public Brush Background { get; set; } = Brushes.Black; + public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(216, 216, 216)); + public Brush IconColor { get; set; } = new SolidColorBrush(Color.FromRgb(255, 255, 255)); + public Brush ProgressBarBackground { get; set; } = new SolidColorBrush(Color.FromRgb(86, 86, 86)); public HyperionDialogViewModel(IBootstrapperDialog dialog) : base(dialog) { } From 85c83af15e4a5685242a89ef45879f0cf3a2aed0 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Thu, 11 May 2023 01:15:07 +0800 Subject: [PATCH 011/178] Fix padding on close button xd --- Bloxstrap/Dialogs/HyperionDialog.xaml | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Bloxstrap/Dialogs/HyperionDialog.xaml b/Bloxstrap/Dialogs/HyperionDialog.xaml index f0677e10..75b19ced 100644 --- a/Bloxstrap/Dialogs/HyperionDialog.xaml +++ b/Bloxstrap/Dialogs/HyperionDialog.xaml @@ -15,7 +15,7 @@ - - + @@ -35,7 +35,7 @@ - + diff --git a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs index 20b8e46c..d1743d5f 100644 --- a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs +++ b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs @@ -8,10 +8,11 @@ namespace Bloxstrap.ViewModels public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChanged { public string Version => $"Bloxstrap v{App.Version}"; + // Using dark theme for default values. public Thickness DialogBorder { get; set; } = new Thickness(0); public Brush Background { get; set; } = Brushes.Black; - public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(216, 216, 216)); + public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(235, 235, 235)); public Brush IconColor { get; set; } = new SolidColorBrush(Color.FromRgb(255, 255, 255)); public Brush ProgressBarBackground { get; set; } = new SolidColorBrush(Color.FromRgb(86, 86, 86)); public ByfronDialogViewModel(IBootstrapperDialog dialog) : base(dialog) From 066fda920e20f5364f800b31fa0d339bb8cf6323 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Sat, 13 May 2023 10:29:21 +0800 Subject: [PATCH 015/178] More corrections to mimic the dialog --- Bloxstrap/Fonts/Rubik-VariableFont_wght.ttf | Bin 0 -> 193736 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Bloxstrap/Fonts/Rubik-VariableFont_wght.ttf diff --git a/Bloxstrap/Fonts/Rubik-VariableFont_wght.ttf b/Bloxstrap/Fonts/Rubik-VariableFont_wght.ttf new file mode 100644 index 0000000000000000000000000000000000000000..547f06974a0a11afca9e5c305544e406a1609d72 GIT binary patch literal 193736 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 ~Rl&Bf`Ai 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 F{a;$^yfXj* literal 0 HcmV?d00001 From 7e82dc4436df49d2a07e477763916635d7349ce9 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Sat, 13 May 2023 10:31:05 +0800 Subject: [PATCH 016/178] Didn't pass the -a flag in git... --- Bloxstrap/App.xaml | 2 ++ Bloxstrap/Bloxstrap.csproj | 1 + Bloxstrap/Dialogs/ByfronDialog.xaml | 8 ++++++-- Bloxstrap/ViewModels/ByfronDialogViewModel.cs | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/App.xaml b/Bloxstrap/App.xaml index 8f4642f9..3ac28c3b 100644 --- a/Bloxstrap/App.xaml +++ b/Bloxstrap/App.xaml @@ -11,6 +11,8 @@ + + pack://application:,,,/Fonts/#Rubik Light diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 05de60f8..60a5348f 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -14,6 +14,7 @@ + diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml b/Bloxstrap/Dialogs/ByfronDialog.xaml index be0b9870..30dd0abb 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml @@ -23,7 +23,7 @@ - + @@ -35,7 +35,11 @@ - + + + + + diff --git a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs index d1743d5f..76090468 100644 --- a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs +++ b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs @@ -12,7 +12,7 @@ public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChang // Using dark theme for default values. public Thickness DialogBorder { get; set; } = new Thickness(0); public Brush Background { get; set; } = Brushes.Black; - public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(235, 235, 235)); + public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(239, 239, 239)); public Brush IconColor { get; set; } = new SolidColorBrush(Color.FromRgb(255, 255, 255)); public Brush ProgressBarBackground { get; set; } = new SolidColorBrush(Color.FromRgb(86, 86, 86)); public ByfronDialogViewModel(IBootstrapperDialog dialog) : base(dialog) From 74d15c9bf38f58fc6e32cb34def670f3475aab29 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Sat, 13 May 2023 11:57:16 +0800 Subject: [PATCH 017/178] Add Byfron logo --- Bloxstrap/Bloxstrap.csproj | 4 +++- Bloxstrap/Bootstrapper.cs | 2 ++ Bloxstrap/Dialogs/BootstrapperDialogForm.cs | 3 +++ Bloxstrap/Dialogs/ByfronDialog.xaml | 3 ++- Bloxstrap/Dialogs/ByfronDialog.xaml.cs | 13 ++++++++++++- Bloxstrap/Dialogs/FluentDialog.xaml.cs | 3 +++ Bloxstrap/Dialogs/IBootstrapperDialog.cs | 1 + Bloxstrap/Properties/Resources.Designer.cs | 2 +- Bloxstrap/Resources/ByfronLogo.png | Bin 0 -> 15113 bytes Bloxstrap/Resources/ByfronLogoDark.png | Bin 0 -> 19543 bytes Bloxstrap/ViewModels/AppearanceViewModel.cs | 2 ++ Bloxstrap/ViewModels/ByfronDialogViewModel.cs | 10 +++++++++- 12 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 Bloxstrap/Resources/ByfronLogo.png create mode 100644 Bloxstrap/Resources/ByfronLogoDark.png diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 60a5348f..84c8b59f 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -14,7 +14,9 @@ - + + + diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 5b915ebe..5d57f8c6 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -709,6 +709,8 @@ private async Task InstallLatestVersion() { Dialog.CancelEnabled = true; Dialog.ProgressStyle = ProgressBarStyle.Continuous; + // Byfron dialog specific + Dialog.VersionVisibility = false; } // compute total bytes to download diff --git a/Bloxstrap/Dialogs/BootstrapperDialogForm.cs b/Bloxstrap/Dialogs/BootstrapperDialogForm.cs index 64e5c5f3..3bff2447 100644 --- a/Bloxstrap/Dialogs/BootstrapperDialogForm.cs +++ b/Bloxstrap/Dialogs/BootstrapperDialogForm.cs @@ -63,6 +63,9 @@ public bool CancelEnabled _cancelEnabled = value; } } + + // Byfron specific - not required here, bypassing + public bool VersionVisibility { get; set; } #endregion public void ScaleWindow() diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml b/Bloxstrap/Dialogs/ByfronDialog.xaml index 30dd0abb..6bbaa090 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml @@ -15,6 +15,7 @@ + - + diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs index 92b01d61..6ac5cce9 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs @@ -2,7 +2,7 @@ using System.Windows; using System.Windows.Forms; using System.Windows.Media; - +using System.Windows.Media.Imaging; using Bloxstrap.Enums; using Bloxstrap.Extensions; using Bloxstrap.ViewModels; @@ -58,6 +58,16 @@ public bool CancelEnabled _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); } } + + public bool VersionVisibility + { + get => _viewModel.VersionNumberVisibility == Visibility.Collapsed; + set + { + _viewModel.VersionNumberVisibility = (value ? Visibility.Visible : Visibility.Collapsed); + _viewModel.OnPropertyChanged(nameof(_viewModel.VersionNumberVisibility)); + } + } #endregion public ByfronDialog() @@ -75,6 +85,7 @@ public ByfronDialog() _viewModel.Foreground = new SolidColorBrush(Color.FromRgb(57, 59, 61)); _viewModel.IconColor = new SolidColorBrush(Color.FromRgb(57, 59, 61)); _viewModel.ProgressBarBackground = new SolidColorBrush(Color.FromRgb(189, 190, 190)); + _viewModel.ByfronLogo = new BitmapImage(new Uri("pack://application:,,,/Bloxstrap;component/Resources/ByfronLogoDark.png")); } InitializeComponent(); diff --git a/Bloxstrap/Dialogs/FluentDialog.xaml.cs b/Bloxstrap/Dialogs/FluentDialog.xaml.cs index ff65b081..dd88b7cc 100644 --- a/Bloxstrap/Dialogs/FluentDialog.xaml.cs +++ b/Bloxstrap/Dialogs/FluentDialog.xaml.cs @@ -63,6 +63,9 @@ public bool CancelEnabled _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); } } + + // Byfron specific - not required here, bypassing + public bool VersionVisibility { get; set; } #endregion public FluentDialog() diff --git a/Bloxstrap/Dialogs/IBootstrapperDialog.cs b/Bloxstrap/Dialogs/IBootstrapperDialog.cs index e66b6875..53b816b2 100644 --- a/Bloxstrap/Dialogs/IBootstrapperDialog.cs +++ b/Bloxstrap/Dialogs/IBootstrapperDialog.cs @@ -10,6 +10,7 @@ public interface IBootstrapperDialog ProgressBarStyle ProgressStyle { get; set; } int ProgressValue { get; set; } bool CancelEnabled { get; set; } + bool VersionVisibility { get; set; } void ShowBootstrapper(); void CloseBootstrapper(); diff --git a/Bloxstrap/Properties/Resources.Designer.cs b/Bloxstrap/Properties/Resources.Designer.cs index 202cd2e8..2e365792 100644 --- a/Bloxstrap/Properties/Resources.Designer.cs +++ b/Bloxstrap/Properties/Resources.Designer.cs @@ -59,7 +59,7 @@ internal Resources() { resourceCulture = value; } } - + ///

/// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/Bloxstrap/Resources/ByfronLogo.png b/Bloxstrap/Resources/ByfronLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..5e0c9e8721212f48d6e15c9a0d4971fd098d83a5 GIT binary patch literal 15113 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

3oAyk-M;{J@OknAR^zdstw?QJSZ_42o1ODEKc{ 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�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 E0ZAhxj{pDw literal 0 HcmV?d00001 diff --git a/Bloxstrap/ViewModels/AppearanceViewModel.cs b/Bloxstrap/ViewModels/AppearanceViewModel.cs index ba85815f..228385c5 100644 --- a/Bloxstrap/ViewModels/AppearanceViewModel.cs +++ b/Bloxstrap/ViewModels/AppearanceViewModel.cs @@ -36,6 +36,8 @@ private void PreviewBootstrapper() dialog.Message = "Style preview - Click Cancel to close"; dialog.CancelEnabled = true; + // Byfron dialog specific + dialog.VersionVisibility = false; dialog.ShowBootstrapper(); } diff --git a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs index 76090468..4b5405c1 100644 --- a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs +++ b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs @@ -1,7 +1,10 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; using System.Windows; using System.Windows.Media; +using System.Windows.Media.Imaging; using Bloxstrap.Dialogs; +using Bloxstrap.Extensions; namespace Bloxstrap.ViewModels { @@ -15,6 +18,11 @@ public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChang public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(239, 239, 239)); public Brush IconColor { get; set; } = new SolidColorBrush(Color.FromRgb(255, 255, 255)); public Brush ProgressBarBackground { get; set; } = new SolidColorBrush(Color.FromRgb(86, 86, 86)); + public ImageSource ByfronLogo { get; set; } = new BitmapImage(new Uri("pack://application:,,,/Bloxstrap;component/Resources/ByfronLogo.png")); + + // When cancel button is visible, version number is hidden. + public Visibility VersionNumberVisibility { get; set; } = Visibility.Collapsed; + public ByfronDialogViewModel(IBootstrapperDialog dialog) : base(dialog) { } From 2a24a0526fe470d719dbc9b1303dffbf46eb1059 Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Sat, 13 May 2023 12:05:20 +0800 Subject: [PATCH 018/178] Fix padding and visibility --- Bloxstrap/Dialogs/ByfronDialog.xaml | 2 +- Bloxstrap/Dialogs/ByfronDialog.xaml.cs | 2 +- Bloxstrap/ViewModels/ByfronDialogViewModel.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml b/Bloxstrap/Dialogs/ByfronDialog.xaml index 6bbaa090..1e779edf 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml @@ -23,7 +23,7 @@ - + diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs index 6ac5cce9..411930c2 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs @@ -61,7 +61,7 @@ public bool CancelEnabled public bool VersionVisibility { - get => _viewModel.VersionNumberVisibility == Visibility.Collapsed; + get => _viewModel.VersionNumberVisibility == Visibility.Visible; set { _viewModel.VersionNumberVisibility = (value ? Visibility.Visible : Visibility.Collapsed); diff --git a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs index 4b5405c1..bbaefdbf 100644 --- a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs +++ b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs @@ -21,7 +21,7 @@ public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChang public ImageSource ByfronLogo { get; set; } = new BitmapImage(new Uri("pack://application:,,,/Bloxstrap;component/Resources/ByfronLogo.png")); // When cancel button is visible, version number is hidden. - public Visibility VersionNumberVisibility { get; set; } = Visibility.Collapsed; + public Visibility VersionNumberVisibility { get; set; } = Visibility.Visible; public ByfronDialogViewModel(IBootstrapperDialog dialog) : base(dialog) { From 58932f4b340a81f4b12a9fcb9349e217add307da Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Sat, 13 May 2023 12:13:15 +0800 Subject: [PATCH 019/178] =?UTF-8?q?i=20forgor=20=F0=9F=92=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bloxstrap/Bootstrapper.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 5d57f8c6..44d4e0d5 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -793,7 +793,11 @@ private async Task InstallLatestVersion() } if (Dialog is not null) + { Dialog.CancelEnabled = false; + // Byfron dialog specific + Dialog.VersionVisibility = true; + } App.State.Prop.VersionGuid = _latestVersionGuid; From 969dbbbf922e7bb2b86c6553b663e23410a5622c Mon Sep 17 00:00:00 2001 From: 1011025m <37438176+1011025m@users.noreply.github.com> Date: Sat, 13 May 2023 20:43:13 +0800 Subject: [PATCH 020/178] Regression, it didn't have to be over engineered --- Bloxstrap/Bootstrapper.cs | 6 ------ Bloxstrap/Dialogs/BootstrapperDialogForm.cs | 3 --- Bloxstrap/Dialogs/ByfronDialog.xaml.cs | 10 +--------- Bloxstrap/Dialogs/FluentDialog.xaml.cs | 3 --- Bloxstrap/Dialogs/IBootstrapperDialog.cs | 1 - Bloxstrap/ViewModels/AppearanceViewModel.cs | 2 -- 6 files changed, 1 insertion(+), 24 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 44d4e0d5..5b915ebe 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -709,8 +709,6 @@ private async Task InstallLatestVersion() { Dialog.CancelEnabled = true; Dialog.ProgressStyle = ProgressBarStyle.Continuous; - // Byfron dialog specific - Dialog.VersionVisibility = false; } // compute total bytes to download @@ -793,11 +791,7 @@ private async Task InstallLatestVersion() } if (Dialog is not null) - { Dialog.CancelEnabled = false; - // Byfron dialog specific - Dialog.VersionVisibility = true; - } App.State.Prop.VersionGuid = _latestVersionGuid; diff --git a/Bloxstrap/Dialogs/BootstrapperDialogForm.cs b/Bloxstrap/Dialogs/BootstrapperDialogForm.cs index 3bff2447..64e5c5f3 100644 --- a/Bloxstrap/Dialogs/BootstrapperDialogForm.cs +++ b/Bloxstrap/Dialogs/BootstrapperDialogForm.cs @@ -63,9 +63,6 @@ public bool CancelEnabled _cancelEnabled = value; } } - - // Byfron specific - not required here, bypassing - public bool VersionVisibility { get; set; } #endregion public void ScaleWindow() diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs index 411930c2..3a0a1f78 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs @@ -55,16 +55,8 @@ public bool CancelEnabled set { _viewModel.CancelButtonVisibility = (value ? Visibility.Visible : Visibility.Collapsed); + _viewModel.VersionNumberVisibility = (value ? Visibility.Collapsed : Visibility.Visible); _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); - } - } - - public bool VersionVisibility - { - get => _viewModel.VersionNumberVisibility == Visibility.Visible; - set - { - _viewModel.VersionNumberVisibility = (value ? Visibility.Visible : Visibility.Collapsed); _viewModel.OnPropertyChanged(nameof(_viewModel.VersionNumberVisibility)); } } diff --git a/Bloxstrap/Dialogs/FluentDialog.xaml.cs b/Bloxstrap/Dialogs/FluentDialog.xaml.cs index dd88b7cc..ff65b081 100644 --- a/Bloxstrap/Dialogs/FluentDialog.xaml.cs +++ b/Bloxstrap/Dialogs/FluentDialog.xaml.cs @@ -63,9 +63,6 @@ public bool CancelEnabled _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); } } - - // Byfron specific - not required here, bypassing - public bool VersionVisibility { get; set; } #endregion public FluentDialog() diff --git a/Bloxstrap/Dialogs/IBootstrapperDialog.cs b/Bloxstrap/Dialogs/IBootstrapperDialog.cs index 53b816b2..e66b6875 100644 --- a/Bloxstrap/Dialogs/IBootstrapperDialog.cs +++ b/Bloxstrap/Dialogs/IBootstrapperDialog.cs @@ -10,7 +10,6 @@ public interface IBootstrapperDialog ProgressBarStyle ProgressStyle { get; set; } int ProgressValue { get; set; } bool CancelEnabled { get; set; } - bool VersionVisibility { get; set; } void ShowBootstrapper(); void CloseBootstrapper(); diff --git a/Bloxstrap/ViewModels/AppearanceViewModel.cs b/Bloxstrap/ViewModels/AppearanceViewModel.cs index 228385c5..ba85815f 100644 --- a/Bloxstrap/ViewModels/AppearanceViewModel.cs +++ b/Bloxstrap/ViewModels/AppearanceViewModel.cs @@ -36,8 +36,6 @@ private void PreviewBootstrapper() dialog.Message = "Style preview - Click Cancel to close"; dialog.CancelEnabled = true; - // Byfron dialog specific - dialog.VersionVisibility = false; dialog.ShowBootstrapper(); } From 9da925cd5489e0ed25ad3a17a991492af0e83b97 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 13 May 2023 14:23:32 +0100 Subject: [PATCH 021/178] Add fake Byfron logo Also undo some changes for version number and stuff, I'll do that later in a sec --- Bloxstrap/App.xaml | 2 +- Bloxstrap/Bloxstrap.csproj | 6 ++-- Bloxstrap/Dialogs/ByfronDialog.xaml | 27 +++++++----------- Bloxstrap/Dialogs/ByfronDialog.xaml.cs | 5 ++-- .../ByfronDialog/ByfronLogoDark.jpg | Bin 0 -> 6262 bytes .../ByfronDialog/ByfronLogoLight.jpg | Bin 0 -> 5718 bytes Bloxstrap/Resources/ByfronLogo.png | Bin 15113 -> 0 bytes Bloxstrap/Resources/ByfronLogoDark.png | Bin 19543 -> 0 bytes .../Fonts/Rubik-VariableFont_wght.ttf | Bin Bloxstrap/ViewModels/ByfronDialogViewModel.cs | 7 ++--- 10 files changed, 19 insertions(+), 28 deletions(-) create mode 100644 Bloxstrap/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoDark.jpg create mode 100644 Bloxstrap/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoLight.jpg delete mode 100644 Bloxstrap/Resources/ByfronLogo.png delete mode 100644 Bloxstrap/Resources/ByfronLogoDark.png rename Bloxstrap/{ => Resources}/Fonts/Rubik-VariableFont_wght.ttf (100%) diff --git a/Bloxstrap/App.xaml b/Bloxstrap/App.xaml index 3ac28c3b..c46ad487 100644 --- a/Bloxstrap/App.xaml +++ b/Bloxstrap/App.xaml @@ -12,7 +12,7 @@ - pack://application:,,,/Fonts/#Rubik Light + pack://application:,,,/Resources/Fonts/#Rubik Light diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 84c8b59f..544d5cb1 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml b/Bloxstrap/Dialogs/ByfronDialog.xaml index 1e779edf..2747e058 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml @@ -12,21 +12,17 @@ WindowStartupLocation="CenterScreen" AllowsTransparency="True" Background="Transparent"> - - - - - - - - - + + + + + @@ -44,6 +40,5 @@ - diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs index 3a0a1f78..f9aa6710 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs @@ -3,6 +3,7 @@ using System.Windows.Forms; using System.Windows.Media; using System.Windows.Media.Imaging; + using Bloxstrap.Enums; using Bloxstrap.Extensions; using Bloxstrap.ViewModels; @@ -55,9 +56,7 @@ public bool CancelEnabled set { _viewModel.CancelButtonVisibility = (value ? Visibility.Visible : Visibility.Collapsed); - _viewModel.VersionNumberVisibility = (value ? Visibility.Collapsed : Visibility.Visible); _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); - _viewModel.OnPropertyChanged(nameof(_viewModel.VersionNumberVisibility)); } } #endregion @@ -77,7 +76,7 @@ public ByfronDialog() _viewModel.Foreground = new SolidColorBrush(Color.FromRgb(57, 59, 61)); _viewModel.IconColor = new SolidColorBrush(Color.FromRgb(57, 59, 61)); _viewModel.ProgressBarBackground = new SolidColorBrush(Color.FromRgb(189, 190, 190)); - _viewModel.ByfronLogo = new BitmapImage(new Uri("pack://application:,,,/Bloxstrap;component/Resources/ByfronLogoDark.png")); + _viewModel.ByfronLogoLocation = new BitmapImage(new Uri("pack://application:,,,/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoLight.jpg")); } InitializeComponent(); diff --git a/Bloxstrap/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoDark.jpg b/Bloxstrap/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoDark.jpg new file mode 100644 index 0000000000000000000000000000000000000000..770e46b1c313f8d70de539f03b731302f6ce7588 GIT binary patch literal 6262 zcmbVQdpwi>+rL@PG-n}}Qz@qsA+pLBNm40t+}EMRLQ1TfjpP(1DoSNJr4nn7#j@|r z94a~H7&|ysl1(*tHrsRS_q?9p>-D^zKc46L>~&rHZ1?AL-`D%T-g{ryJ<*7W2`C

*E;i3^{*QMpj*8gQk|z<}Jos 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

3oAyk-M;{J@OknAR^zdstw?QJSZ_42o1ODEKc{ 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�OjhYU)R2m}J29o_vkA8^9+(ghtG(O7|H-VV~Te!~-n1?atF?|i*&k6hS zi_7sv)bm0$N>?B({-_wyB;Pn!!P$MI3p}1M0#`*l8#h3&GgwX8%K4eeI*3RKSVC%8 z;JG9!T$(!D_5rur*-s_gKXkRITZGmUzq*oOBAcAyAgZz3>MVW|OfKoMq)N3$y>e3Q z^FM{T5}dQGix#Ql9TD#B|5ZT-wG6|B4VU!h0 z(&|Ss9!eL`*(Q2aHU2l2xJ?l(*+w&BSPQwvP{L+K%J*r5KB$&7%>B&Ko<%&l9>jqG z=mheIU#D#UCY;)@U_HX<5pv+g6Sn#l&9(@_!Ot}J9}C&t(&LDvKdob)JC`w`j^S)B zW<3c;hoW$_ax1>A1y_vx6of`&xhrI()zsCS<`y<;X_5M%KUztM+va#dm6l)|j`?3CUHpw);!}LIC)9hbNJw_V4_zqm-ant%)J*;Hse;q;@!>H}MZhju&|RmwcqEBTFM;Q0~&)_w)WVK_QtvKW#w=`XOaP5Zb!&ALIYpJ3SO>{l){QFBe{D-^pC%rRUOZVa7 zCj05Ieq#QOSA=2yH;63LSHhMV)VaBSMWhR?9gcG97Cy(F_U|`G%b~f83FaFQ(xBrX z_j*C#bZ-tXXPC9vP2_rD1ybegzY#{Y?Auu?rUSZnyysFQoXoGao2cmWVY zzN;h##2murj<@$MU#^2sCf#|2=m|<|p+f{0vJ*(!%b9%YRK@aC2t3OOK8gg~h^m{i zHvJDCX7ZHuj&}L(AhuDy2vGnbGOfn!SvvyzkAd?_S{3QIhQKMUi1Ho}uW&@%&+PhU z=ha2I$&HQ~J(?uKiS>Epoc?J)K#qx*ZQ$AJ{x31C=MGr4#wo)Q4VXOV%Gl*R$h?8I zgOw^K0v3n*l~>)$fF%XmLaj3uC{&4eO%X?5NG~YeL_d8H)|eF%ZJO3AylWwx9o7J$ z<Ftzi z_7>FdF(<-|Z(SB#o*RM>Hm3Ty zpUkwp>nF;nxN#I4!g)IPjW%2f+ig!Ghz(r6-%AWA&F{et4C z(IfsgUxq@<$k0neyYYjeD`KoIGW*EO;YrCSe<(^tL@;wY zVmLRY4)eV?hinaVi^Ays#f)BKtt^(z;KjiVZT{c&doA6XW?Lt>DMrc?8To4&UqTXL zZPg=Tmr63b@!38(LS~(?VDMIJsbP`(PCTg~T9VcHWbSPQClFW-^IqcdCWR_C)_hHO zAIlmJ__YE=VD+6N{Mp_b3&ETZ3D8R5mYHQTIlB+LGoljfShwAQ@x!Cf$r{4i3@GjWm=wmXExuI9xu=vJ^G<7F?GJx)kqGCDREYP_@tw_ zU|o6&94kTB`)g*~^Z-ku`nWcSR)_fv)&mTKJdW*Yp=`M1A`UZ1>R~4mW8m|;{kN`F&KI3lh)sM0# zCqimx6iN?X-qx!m9)D4q(?oTxs54EfS9dI{l6MD?&fZ1^JFX1VEn7Nxmae{B%3PxF z*R!bK9iob78~8eogE_=uG`q zlcs*yf0G}}i_NCrw~G69v#UHW`?JCZ!BO>QEf2CNF-Y>aXxyH1b`gj;cyIRzZzZ7{ z`hBR?E}cn&R&K$+KivIKX^QH8+RP!1fGs9NMAn$KfJz|BovuT&D>eY2%7!oU}D8^}e-ue2#+)?dCu&>@;>JJ%X`kQbmVirv3LP!p)<5Df9Y zy252t{m@ny#EQzZpH-H&l5NvZBl#Q6tZyOH=c5Md@jc&iB5NEI8bJQGzVs&3Aup`^kIp{W$9d%)_XEC?r@Pav z_25zj%>IX7#``7KIBuGkA_vwoWZHD^`p0G~%&Zb@8H>yfuw@AT8py6`ld`>Zt( zEik#$AAn_2vSq<+>RBSj9l!J9hZdD(yp%p7%m|lmL@62MO=+(kQklLiH&jN5a@yFY z$RLH-5`|RbnjiPHo$m~%zAKM#&e?Ivk9%To*);lgl8?l)Gp6oOU*ZG8`)oNxCr&-y5v_y-gb!nU_{7W`R?zHNzB zKrigpgvA%BYu_a;HW2Jh2hw~@4m(_~>2%WinzLyTyu5BZi1(za&V+YGYc0$;kMXra zy{Y)3!lGJmpWyL>KA$oX;rFf%M~AN&ij@ zPX-H3dGiczE741dDyEr7GcvR$7s^cYge}#mz-WAaOp9H5&e!mY!K2mWTa^*&!o2}D z>ExW4y7jL0Hm+Ac`k4ppZ}d@r4cr7bwZ0mWv-gq#UkuvrBC8*tGHjC9VJI+!)y1Q} zIt!Qk6o+|rGm!gAsP%SwD_1-HpJh*9Q)ukrZ&I7O0+&I6^j4$h8+op`K_!96LTBE+ zTz0)nk*R~`ef49RxA21o4T-OkW3Q@u$-Ah+boP<4bam82sk_Dnc}NDp9AH}NlIot&_Bhn zr78SNmw>rLJFl`Y8z;Xw;#hT7){7D%GHY~MCxUi7}1};0}gSvMEeM@ zqKOhxW;Xn*#Z4!2rN=i17VmH!9Jh@B(o7W$x-{#k@)7&gOZt`p8B)-u5atF zi4qyG2z$h^de#A|69@p+=KYWWGP%GJq)F2jt%p_a{naJ{7*SRfTc7bRCj9#eGGFBp zKI=t2GQ07p$Hs}}L(b@#Ew1fe*NW(`FU#qaS9Hi!VY`W)n2i0vm?1%=|=gE z5-p%#Pj(>7m*kA7Q-yn2_CsQzJviPyEB-qz!apNo!A{K&TyKz9#KdWNeOu3kC1;r zt&ne$D7L^b?r5mft}L`3`&|snCiqbuxjhzvG4j0e+&FfGEA`R-Ep~2-d(7!tPQ{9t z==o=y^7q)7>9oABJb@bv%dk+I-)7QCW{_0h0eQv7MnxX^TL5x2b8vg)9X}P%4>1Wn zk4>0b-*R`8_$DT;*PG0}+EH0v)hRH6oxft!o^>iUU(2!il$jFRadS|N^!5dTE^EFT z86{;zV82^{q?=YN;9YoTYU(cetR6wLmmecX??l=4L(5JSX&94ae)1*n%)IsH{~TU> zL|+*IlftxN0Li9wfml32yL-@XpzKGP`0EQC9`wYnnr=)M(F9x~V{-n`y8zYLh^6zm0d^f;dfc<{oyXeSP4(lf*JxSWP?IE*S?w&- za*WUst?K>LM3S@nrj?5Y^i36oT=D5Ut-3@j&AOpH9e0}!p8e`u;!Avdr-$+%L?viy0MI=SM^4}L;DSvA}ShRh^wH{HKr!P6Tfj zf9bQ6wOAw@j?wHwj2=8X$wRGA{9CoIRx^i|T=rU?5ScIRGTz|G-Q0(5debYPXd_@z zrM>5abbsMcl#Ob$kYVw2k@m%k1o^%@o{R*Cmg(9(DSU{yg|X+9qYXMe&Z(cz{WFgg zrT@pr1^+`~Ieu*$hgdvgPs>cp*p+Z6>1;_^8phyugl!{!BkQi`ySmH>CWv#w%g$rAUe04JT+>GvhHJ7@(jHGcGs!kspiZ?rK)bi!^7TKK;xmzP zkz9zNozQpD*gL_hvUH1LDX%%R^fE8Y@jqv;h~0_*VUe}uSwlu&75un=UM48Owh2s+ zmx9}qdFd44#M((gpStT!jgkCSls&pXb8@UBXQ$kn?Es-KS1pDvwabol&uzEpaGf94 zLwfG?gL7G3AF&cB8@ev7%QebULVb#RIo(Njf`MG>fa0i}EacL7MCXKsvF^~Frdh^A z$!1lNb$-+%yex7vFWLJEBi(#Kkm)m;E}AZI-V->dZ?f0=nJ;Xv&lS-N99i{5u6F)_ zDTD9F)!H5XQ}PE8m^+O4wCP0c$Jy%qtqm23GDyRCXY1TG0{_qsfnG3T6If5I&>_H; zk)$v#Bb=Cu+~9GUe)05m>4Ofs`~%acMw92|gM;J6Dp4Y542KB! zG1@*^$YXZA(|M&&=KUR?e%gL2L?|MnKXaB=?<d-#9@!e=UTt)( z+yIgr&%&v#mRoLwS>WwJX$EEz`}$X!ZNQ!2a}4R%@8?@M)!@=87dVIy$F=r6n6{Y? zU3-g-yf1ePu=2f4MQ2YYK*#tc1ReNk#_#y%F5B?@D4Nqt{-~g`1y1endP-(X2P23u zZfJqa70F*y4`-fVvSXP56mG3WM1f8#V@eB;B74r1PjIdtn6X>{$6`ZU%8@17BYH}| zzbXjT-mwzYYiGhScmK zeBDyE6;XexhVo}?>Q0;XYRU1auLiw5DSE>vJt8~1~I^0{--oI1-+)%^>KU%Chx=;ebX8} zdR4V`>W`KhJraSY&egi@l|OjJEC&SJ^Z82;;@2bSwnOE6#2=vZTb10p37yt&O|{E?psEj|{O9Xt+Z!iTD6~M`Zt*>~J=N zQ}LpE(N2l}?Nc%AYJ#80?H6v}Nu|lZn_xsNm|q$>=hjVM4Y260q`VJEH?VlO$%38( zLeom=CoFTl>ciWg1Qzt1(++cYjzx3|tm@zT6~TdVRF2A1pN8MbgG8$_*ROs%mh#tc zr992)X&-KWYQ3=!y52a74~MTFy!wF_g8XKSW-lg63AEkE@7Kn=PV_uc^C>&r_uMhz zljs^4oM9}=(}L|F=p=8LnVm^fXXu_jxAcr=?9`vC2Oe?^{IXoK})Jqc*nCJt^2{SfPevy=lj2i%HlIZ*{^Df{5)lF``Gwa|>mv3R->DJWSB%f4!eSe!-_O^HtOQ=l+8%Gjg!Z;69j$&YjP0?m@Fe(n zQupMZPd7h#}q0h04sIUH|V)4fAvk;@&_MiL}wBncA zZl;23`lCnM@Y9s)U)l-?A!Qbpxx$K4Q}4b;k^K%-nU%z{^JlGkf(ytJrb0~x#|xji zVR$c}Ro(usf28`TRF02w3_12dKRCgJKU8N9-R4DJh*DM;kk}Sm zGgY_8enNO6E`L7RA;C>XVverP39;QXfivou!%WKR5OkHCVBoaSkv*sXk}rg>BB??p z%+TVa75-9&Pk!yuRkL-=B4`eCq#L81-P2;vk1P?I&UlAgfgjR4PVuK*9?kWmC0^Cw)uL6pwFNavoHs76xv z6mWX+vlRAc+(F=>rj@{cf5+}T&|sE_pa)iEPx++SZhXRc3I@@On_9;HkHPkuxz zctiMTdKAzEV@X9pF5nX`V)83MiQzzHYc(?T&)Z#YGk#X9Hk>7E<>r`?_^sS}Ukw5C zNY^qilj6{$PUp}`1Z=gKl+}6$o`g``D5#Hi|-inY4HUE z4Jv!E$duV!%~p731Q}sFid-{GrJAEI(aEtegn@^z@;44@C#sUB2iNO`b&PVvV5nxW z;O9%mYEH@9>z4bFrAI3q_KGpktr;avK z6ysZ!<6DkxhZfHC7uRel5GSVlJe*;l1)EBGvsaC>rAe)QPZ4`u^}R)#y;5f%c(bFh z7WD;Rml??My7O`9vy%?q`Zm}IKBe^&@pGm>-Es{tepp{;kLzW+W2lJ}*Zn2lapO4~ zzaAsuZiBf4Z}J{{`>&EF8h_v!3JDjVK!{O|;wweJkobVI<;=?HW$2q)mu8_3NBZA+ zsoZZGwca+7ecC-0sK{C7%e4G1no(gi;UEqj6#MynJYNH`&-G1d@SbW!rq^W-%2$HN z^?E$?0_xp_)A)^~wN`r|I})5&WNO;~-yF0y?20Yvk8bM}QQ;o&#uuckWvJPx?(pFM E0ZAhxj{pDw diff --git a/Bloxstrap/Fonts/Rubik-VariableFont_wght.ttf b/Bloxstrap/Resources/Fonts/Rubik-VariableFont_wght.ttf similarity index 100% rename from Bloxstrap/Fonts/Rubik-VariableFont_wght.ttf rename to Bloxstrap/Resources/Fonts/Rubik-VariableFont_wght.ttf diff --git a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs index bbaefdbf..30cae23a 100644 --- a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs +++ b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs @@ -3,8 +3,8 @@ using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; + using Bloxstrap.Dialogs; -using Bloxstrap.Extensions; namespace Bloxstrap.ViewModels { @@ -13,15 +13,12 @@ public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChang public string Version => $"Bloxstrap v{App.Version}"; // Using dark theme for default values. + public ImageSource ByfronLogoLocation { get; set; } = new BitmapImage(new Uri("pack://application:,,,/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoDark.jpg")); public Thickness DialogBorder { get; set; } = new Thickness(0); public Brush Background { get; set; } = Brushes.Black; public Brush Foreground { get; set; } = new SolidColorBrush(Color.FromRgb(239, 239, 239)); public Brush IconColor { get; set; } = new SolidColorBrush(Color.FromRgb(255, 255, 255)); public Brush ProgressBarBackground { get; set; } = new SolidColorBrush(Color.FromRgb(86, 86, 86)); - public ImageSource ByfronLogo { get; set; } = new BitmapImage(new Uri("pack://application:,,,/Bloxstrap;component/Resources/ByfronLogo.png")); - - // When cancel button is visible, version number is hidden. - public Visibility VersionNumberVisibility { get; set; } = Visibility.Visible; public ByfronDialogViewModel(IBootstrapperDialog dialog) : base(dialog) { From 1f91c309ca94828998bb692beb5b909e825932d2 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 14 May 2023 01:39:28 +0100 Subject: [PATCH 022/178] Add client version number Finalizing the fake Byfron style --- Bloxstrap/Bootstrapper.cs | 9 +++++--- Bloxstrap/Dialogs/ByfronDialog.xaml | 7 +++--- Bloxstrap/Dialogs/ByfronDialog.xaml.cs | 3 +++ Bloxstrap/ViewModels/ByfronDialogViewModel.cs | 23 +++++++++++++++++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 5b915ebe..8df2c368 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -17,7 +17,6 @@ using Bloxstrap.Integrations; using Bloxstrap.Models; using Bloxstrap.Tools; -using System.Globalization; namespace Bloxstrap { @@ -111,6 +110,10 @@ private void SetStatus(string message) { App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); + // yea idk + if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) + message = message.Replace("...", ""); + if (Dialog is not null) Dialog.Message = message; } @@ -790,11 +793,11 @@ private async Task InstallLatestVersion() } } + App.State.Prop.VersionGuid = _latestVersionGuid; + if (Dialog is not null) Dialog.CancelEnabled = false; - App.State.Prop.VersionGuid = _latestVersionGuid; - _isInstalling = false; } diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml b/Bloxstrap/Dialogs/ByfronDialog.xaml index 2747e058..d2cda202 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml @@ -15,24 +15,25 @@ - + - + - + diff --git a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs index f9aa6710..a689121e 100644 --- a/Bloxstrap/Dialogs/ByfronDialog.xaml.cs +++ b/Bloxstrap/Dialogs/ByfronDialog.xaml.cs @@ -57,6 +57,9 @@ public bool CancelEnabled { _viewModel.CancelButtonVisibility = (value ? Visibility.Visible : Visibility.Collapsed); _viewModel.OnPropertyChanged(nameof(_viewModel.CancelButtonVisibility)); + + _viewModel.OnPropertyChanged(nameof(_viewModel.VersionTextVisibility)); + _viewModel.OnPropertyChanged(nameof(_viewModel.VersionText)); } } #endregion diff --git a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs index 30cae23a..6178606a 100644 --- a/Bloxstrap/ViewModels/ByfronDialogViewModel.cs +++ b/Bloxstrap/ViewModels/ByfronDialogViewModel.cs @@ -1,5 +1,7 @@ using System; using System.ComponentModel; +using System.Diagnostics; +using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -10,8 +12,6 @@ namespace Bloxstrap.ViewModels { public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChanged { - public string Version => $"Bloxstrap v{App.Version}"; - // Using dark theme for default values. public ImageSource ByfronLogoLocation { get; set; } = new BitmapImage(new Uri("pack://application:,,,/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoDark.jpg")); public Thickness DialogBorder { get; set; } = new Thickness(0); @@ -20,6 +20,25 @@ public class ByfronDialogViewModel : FluentDialogViewModel, INotifyPropertyChang public Brush IconColor { get; set; } = new SolidColorBrush(Color.FromRgb(255, 255, 255)); public Brush ProgressBarBackground { get; set; } = new SolidColorBrush(Color.FromRgb(86, 86, 86)); + public Visibility VersionTextVisibility => CancelButtonVisibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed; + public string VersionText + { + get + { + string playerLocation = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid, "RobloxPlayerBeta.exe"); + + if (!File.Exists(playerLocation)) + return ""; + + FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(playerLocation); + + if (versionInfo.ProductVersion is null) + return ""; + + return versionInfo.ProductVersion.Replace(", ", "."); + } + } + public ByfronDialogViewModel(IBootstrapperDialog dialog) : base(dialog) { } From a50a032e84fb8f692f9685dde15b9e6516a8ffc0 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 14 May 2023 01:51:28 +0100 Subject: [PATCH 023/178] credits :D --- Bloxstrap/Views/Pages/AboutPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloxstrap/Views/Pages/AboutPage.xaml b/Bloxstrap/Views/Pages/AboutPage.xaml index a455e90e..9c984ebc 100644 --- a/Bloxstrap/Views/Pages/AboutPage.xaml +++ b/Bloxstrap/Views/Pages/AboutPage.xaml @@ -70,7 +70,7 @@ 1011025m - + sitiom From 6d72ec973ee9c867f86a3dccf01ccab3dcae79ca Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 14 May 2023 02:05:38 +0100 Subject: [PATCH 024/178] Move auto channel change preference moved to installation tab to make it clearer that it's related to channel preference --- Bloxstrap/ViewModels/BehaviourViewModel.cs | 21 +------------------ Bloxstrap/ViewModels/InstallationViewModel.cs | 15 +++++++++++++ Bloxstrap/Views/Pages/BehaviourPage.xaml | 9 -------- Bloxstrap/Views/Pages/InstallationPage.xaml | 9 ++++++++ 4 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Bloxstrap/ViewModels/BehaviourViewModel.cs b/Bloxstrap/ViewModels/BehaviourViewModel.cs index be4812ef..86bb853c 100644 --- a/Bloxstrap/ViewModels/BehaviourViewModel.cs +++ b/Bloxstrap/ViewModels/BehaviourViewModel.cs @@ -1,9 +1,4 @@ -using System.Collections.Generic; -using System.Linq; - -using Bloxstrap.Enums; - -namespace Bloxstrap.ViewModels +namespace Bloxstrap.ViewModels { public class BehaviourViewModel { @@ -24,19 +19,5 @@ public bool MultiInstanceLaunchingEnabled get => App.Settings.Prop.MultiInstanceLaunching; set => App.Settings.Prop.MultiInstanceLaunching = value; } - - // todo - move to enum attributes? - public IReadOnlyDictionary ChannelChangeModes => new Dictionary - { - { "Change automatically", ChannelChangeMode.Automatic }, - { "Always prompt", ChannelChangeMode.Prompt }, - { "Never change", ChannelChangeMode.Ignore }, - }; - - public string SelectedChannelChangeMode - { - get => ChannelChangeModes.FirstOrDefault(x => x.Value == App.Settings.Prop.ChannelChangeMode).Key; - set => App.Settings.Prop.ChannelChangeMode = ChannelChangeModes[value]; - } } } diff --git a/Bloxstrap/ViewModels/InstallationViewModel.cs b/Bloxstrap/ViewModels/InstallationViewModel.cs index 7eca88e5..d64607b1 100644 --- a/Bloxstrap/ViewModels/InstallationViewModel.cs +++ b/Bloxstrap/ViewModels/InstallationViewModel.cs @@ -10,6 +10,7 @@ using CommunityToolkit.Mvvm.Input; +using Bloxstrap.Enums; using Bloxstrap.Models; namespace Bloxstrap.ViewModels @@ -117,5 +118,19 @@ public bool ManualChannelEntry // cant use data bindings so i have to do whatever tf this is public Visibility ChannelComboBoxVisibility => ManualChannelEntry ? Visibility.Collapsed : Visibility.Visible; public Visibility ChannelTextBoxVisibility => ManualChannelEntry ? Visibility.Visible : Visibility.Collapsed; + + // todo - move to enum attributes? + public IReadOnlyDictionary ChannelChangeModes => new Dictionary + { + { "Change automatically", ChannelChangeMode.Automatic }, + { "Always prompt", ChannelChangeMode.Prompt }, + { "Never change", ChannelChangeMode.Ignore }, + }; + + public string SelectedChannelChangeMode + { + get => ChannelChangeModes.FirstOrDefault(x => x.Value == App.Settings.Prop.ChannelChangeMode).Key; + set => App.Settings.Prop.ChannelChangeMode = ChannelChangeModes[value]; + } } } diff --git a/Bloxstrap/Views/Pages/BehaviourPage.xaml b/Bloxstrap/Views/Pages/BehaviourPage.xaml index 0ed442b2..daaa9fe7 100644 --- a/Bloxstrap/Views/Pages/BehaviourPage.xaml +++ b/Bloxstrap/Views/Pages/BehaviourPage.xaml @@ -40,14 +40,5 @@ - - - - - - - - - diff --git a/Bloxstrap/Views/Pages/InstallationPage.xaml b/Bloxstrap/Views/Pages/InstallationPage.xaml index ca4dc892..007f021c 100644 --- a/Bloxstrap/Views/Pages/InstallationPage.xaml +++ b/Bloxstrap/Views/Pages/InstallationPage.xaml @@ -122,5 +122,14 @@ + + + + + + + + + From 64978aecb0877cee5282f82681dc864c0f9bfb93 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 14 May 2023 02:21:21 +0100 Subject: [PATCH 025/178] Add FFlag preset for enabling old textures (#215) --- Bloxstrap/Singletons/FastFlagManager.cs | 3 +++ Bloxstrap/ViewModels/FastFlagsViewModel.cs | 6 ++++++ Bloxstrap/Views/Pages/FastFlagsPage.xaml | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index 4a5b26f2..e52e52be 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -15,6 +15,9 @@ public class FastFlagManager : JsonManager> // to delete a fastflag, set the value to null public Dictionary Changes = new(); + // this is the value of the 'FStringPartTexturePackTablePre2022' flag + public const string OldTexturesFlagValue = "{\"foil\":{\"ids\":[\"rbxassetid://7546645012\",\"rbxassetid://7546645118\"],\"color\":[255,255,255,255]},\"brick\":{\"ids\":[\"rbxassetid://7546650097\",\"rbxassetid://7546645118\"],\"color\":[204,201,200,232]},\"cobblestone\":{\"ids\":[\"rbxassetid://7546652947\",\"rbxassetid://7546645118\"],\"color\":[212,200,187,250]},\"concrete\":{\"ids\":[\"rbxassetid://7546653951\",\"rbxassetid://7546654144\"],\"color\":[208,208,208,255]},\"diamondplate\":{\"ids\":[\"rbxassetid://7547162198\",\"rbxassetid://7546645118\"],\"color\":[170,170,170,255]},\"fabric\":{\"ids\":[\"rbxassetid://7547101130\",\"rbxassetid://7546645118\"],\"color\":[105,104,102,244]},\"glass\":{\"ids\":[\"rbxassetid://7547304948\",\"rbxassetid://7546645118\"],\"color\":[254,254,254,7]},\"granite\":{\"ids\":[\"rbxassetid://7547164710\",\"rbxassetid://7546645118\"],\"color\":[113,113,113,255]},\"grass\":{\"ids\":[\"rbxassetid://7547169285\",\"rbxassetid://7546645118\"],\"color\":[165,165,159,255]},\"ice\":{\"ids\":[\"rbxassetid://7547171356\",\"rbxassetid://7546645118\"],\"color\":[255,255,255,255]},\"marble\":{\"ids\":[\"rbxassetid://7547177270\",\"rbxassetid://7546645118\"],\"color\":[199,199,199,255]},\"metal\":{\"ids\":[\"rbxassetid://7547288171\",\"rbxassetid://7546645118\"],\"color\":[199,199,199,255]},\"pebble\":{\"ids\":[\"rbxassetid://7547291361\",\"rbxassetid://7546645118\"],\"color\":[208,208,208,255]},\"corrodedmetal\":{\"ids\":[\"rbxassetid://7547184629\",\"rbxassetid://7546645118\"],\"color\":[159,119,95,200]},\"sand\":{\"ids\":[\"rbxassetid://7547295153\",\"rbxassetid://7546645118\"],\"color\":[220,220,220,255]},\"slate\":{\"ids\":[\"rbxassetid://7547298114\",\"rbxassetid://7547298323\"],\"color\":[193,193,193,255]},\"wood\":{\"ids\":[\"rbxassetid://7547303225\",\"rbxassetid://7547298786\"],\"color\":[227,227,227,255]},\"woodplanks\":{\"ids\":[\"rbxassetid://7547332968\",\"rbxassetid://7546645118\"],\"color\":[212,209,203,255]},\"asphalt\":{\"ids\":[\"rbxassetid://9873267379\",\"rbxassetid://9438410548\"],\"color\":[123,123,123,234]},\"basalt\":{\"ids\":[\"rbxassetid://9873270487\",\"rbxassetid://9438413638\"],\"color\":[154,154,153,238]},\"crackedlava\":{\"ids\":[\"rbxassetid://9438582231\",\"rbxassetid://9438453972\"],\"color\":[74,78,80,156]},\"glacier\":{\"ids\":[\"rbxassetid://9438851661\",\"rbxassetid://9438453972\"],\"color\":[226,229,229,243]},\"ground\":{\"ids\":[\"rbxassetid://9439044431\",\"rbxassetid://9438453972\"],\"color\":[114,114,112,240]},\"leafygrass\":{\"ids\":[\"rbxassetid://9873288083\",\"rbxassetid://9438453972\"],\"color\":[121,117,113,234]},\"limestone\":{\"ids\":[\"rbxassetid://9873289812\",\"rbxassetid://9438453972\"],\"color\":[235,234,230,250]},\"mud\":{\"ids\":[\"rbxassetid://9873319819\",\"rbxassetid://9438453972\"],\"color\":[130,130,130,252]},\"pavement\":{\"ids\":[\"rbxassetid://9873322398\",\"rbxassetid://9438453972\"],\"color\":[142,142,144,236]},\"rock\":{\"ids\":[\"rbxassetid://9873515198\",\"rbxassetid://9438453972\"],\"color\":[154,154,154,248]},\"salt\":{\"ids\":[\"rbxassetid://9439566986\",\"rbxassetid://9438453972\"],\"color\":[220,220,221,255]},\"sandstone\":{\"ids\":[\"rbxassetid://9873521380\",\"rbxassetid://9438453972\"],\"color\":[174,171,169,246]},\"snow\":{\"ids\":[\"rbxassetid://9439632387\",\"rbxassetid://9438453972\"],\"color\":[218,218,218,255]}}"; + // only one missing here is Metal because lol public static IReadOnlyDictionary RenderingModes => new Dictionary { diff --git a/Bloxstrap/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/ViewModels/FastFlagsViewModel.cs index 6531153e..5993545c 100644 --- a/Bloxstrap/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/ViewModels/FastFlagsViewModel.cs @@ -102,6 +102,12 @@ public bool AlternateGraphicsSelectorEnabled set => App.FastFlags.SetValue("FFlagFixGraphicsQuality", value ? "True" : null); } + public bool Pre2022TexturesEnabled + { + get => App.FastFlags.GetValue("FStringPartTexturePackTable2022") == FastFlagManager.OldTexturesFlagValue; + set => App.FastFlags.SetValue("FStringPartTexturePackTable2022", value ? FastFlagManager.OldTexturesFlagValue : null); + } + public bool MobileLuaAppInterfaceEnabled { get => App.FastFlags.GetValue("FFlagLuaAppSystemBar") == "False"; diff --git a/Bloxstrap/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/Views/Pages/FastFlagsPage.xaml index 1d9ff6a5..4a665757 100644 --- a/Bloxstrap/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/Views/Pages/FastFlagsPage.xaml @@ -56,7 +56,7 @@ - + @@ -82,7 +82,16 @@ - + + + + + + + + + + @@ -92,7 +101,7 @@ - + From cb551ad0d651d9eec0b931ab89be94b318fda003 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 14 May 2023 02:48:33 +0100 Subject: [PATCH 026/178] Add FFlag preset for GUI hiding many thanks to https://github.com/pizzaboxer/bloxstrap/issues/230#issuecomment-1542966228 --- Bloxstrap/ViewModels/FastFlagsViewModel.cs | 42 ++++++++++++---------- Bloxstrap/Views/Pages/FastFlagsPage.xaml | 18 ++++++++-- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/Bloxstrap/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/ViewModels/FastFlagsViewModel.cs index 5993545c..a7b0b7f2 100644 --- a/Bloxstrap/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/ViewModels/FastFlagsViewModel.cs @@ -63,6 +63,18 @@ public bool ExclusiveFullscreenEnabled } } + public bool AlternateGraphicsSelectorEnabled + { + get => App.FastFlags.GetValue("FFlagFixGraphicsQuality") == "True"; + set => App.FastFlags.SetValue("FFlagFixGraphicsQuality", value ? "True" : null); + } + + public bool Pre2022TexturesEnabled + { + get => App.FastFlags.GetValue("FStringPartTexturePackTable2022") == FastFlagManager.OldTexturesFlagValue; + set => App.FastFlags.SetValue("FStringPartTexturePackTable2022", value ? FastFlagManager.OldTexturesFlagValue : null); + } + public IReadOnlyDictionary> IGMenuVersions => FastFlagManager.IGMenuVersions; public string SelectedIGMenuVersion @@ -96,24 +108,6 @@ public string SelectedIGMenuVersion } } - public bool AlternateGraphicsSelectorEnabled - { - get => App.FastFlags.GetValue("FFlagFixGraphicsQuality") == "True"; - set => App.FastFlags.SetValue("FFlagFixGraphicsQuality", value ? "True" : null); - } - - public bool Pre2022TexturesEnabled - { - get => App.FastFlags.GetValue("FStringPartTexturePackTable2022") == FastFlagManager.OldTexturesFlagValue; - set => App.FastFlags.SetValue("FStringPartTexturePackTable2022", value ? FastFlagManager.OldTexturesFlagValue : null); - } - - public bool MobileLuaAppInterfaceEnabled - { - get => App.FastFlags.GetValue("FFlagLuaAppSystemBar") == "False"; - set => App.FastFlags.SetValue("FFlagLuaAppSystemBar", value ? "False" : null); - } - public IReadOnlyDictionary LightingTechnologies => FastFlagManager.LightingTechnologies; // this is basically the same as the code for rendering selection, maybe this could be abstracted in some way? @@ -142,5 +136,17 @@ public string SelectedLightingTechnology App.FastFlags.SetValue(LightingTechnologies[value], "True"); } } + + public bool GuiHidingEnabled + { + get => App.FastFlags.GetValue("DFIntCanHideGuiGroupId") == "32380007"; + set => App.FastFlags.SetValue("DFIntCanHideGuiGroupId", value ? "32380007" : null); + } + + public bool MobileLuaAppInterfaceEnabled + { + get => App.FastFlags.GetValue("FFlagLuaAppSystemBar") == "False"; + set => App.FastFlags.SetValue("FFlagLuaAppSystemBar", value ? "False" : null); + } } } diff --git a/Bloxstrap/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/Views/Pages/FastFlagsPage.xaml index 4a665757..4d0ae466 100644 --- a/Bloxstrap/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/Views/Pages/FastFlagsPage.xaml @@ -13,7 +13,8 @@ - + + @@ -91,8 +92,8 @@ - - + + @@ -106,6 +107,17 @@ + + + + + + TODO - add text for wiki page for controls when done. You must be in the Bloxstrap group for it to work. + + + + + From 22e1623d2380bd935daf1666044d4d9f6f75e77c Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 14 May 2023 02:53:22 +0100 Subject: [PATCH 027/178] Fix bug with ClientAppSettings edit button state --- Bloxstrap/Views/Pages/FastFlagsPage.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/Views/Pages/FastFlagsPage.xaml index 4d0ae466..930d83d3 100644 --- a/Bloxstrap/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/Views/Pages/FastFlagsPage.xaml @@ -21,7 +21,7 @@ - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TODO - add text for wiki page for controls when done. You must be in the Bloxstrap group for it to work. - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TODO - add text for wiki page for controls when done. You must be in the Bloxstrap group for it to work. + + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml index 464f46df..81a9bac1 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml @@ -1,135 +1,134 @@  + + - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml index 5f9021b3..234dfd0e 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml @@ -1,106 +1,106 @@  - - + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml index 1f1b805b..8d0e4f19 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml @@ -1,128 +1,127 @@ - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - A Windows feature that intends to improve fullscreen performance. See here for more information. - - - - - - + + + + + + + + A Windows feature that intends to improve fullscreen performance. See here for more information. + + + + + + From 50bb408e188ad1881fa8fa3d3b96664c33d45acb Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 16 May 2023 10:51:39 +0100 Subject: [PATCH 036/178] Update ci.yml --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1921310c..4d3ab1f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,12 @@ name: CI -on: [push, pull_request] - +on: + push: + paths-ignore: + - 'Resources/**' + pull_request: + paths-ignore: + - 'Resources/**' + jobs: build: strategy: From 00c9bd2e55302660683803d09cec42ac35ace746 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 16 May 2023 11:03:19 +0100 Subject: [PATCH 037/178] Make Resources folder for emoji font mod added as a submodule to ensure it's fixed on a specific commit tag for added security --- .gitmodules | 3 +++ Resources/Mods/rbxcustom-fontemojis | 1 + 2 files changed, 4 insertions(+) create mode 160000 Resources/Mods/rbxcustom-fontemojis diff --git a/.gitmodules b/.gitmodules index 1b06faef..05601267 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "wpfui"] path = wpfui url = https://github.com/pizzaboxer/wpfui.git +[submodule "Resources/Mods/rbxcustom-fontemojis"] + path = Resources/Mods/rbxcustom-fontemojis + url = https://github.com/NikSavchenk0/rbxcustom-fontemojis diff --git a/Resources/Mods/rbxcustom-fontemojis b/Resources/Mods/rbxcustom-fontemojis new file mode 160000 index 00000000..8a552f4a --- /dev/null +++ b/Resources/Mods/rbxcustom-fontemojis @@ -0,0 +1 @@ +Subproject commit 8a552f4aaaecfa58d6bd9b0540e1ac16e81faadb From 95fcdf4edaf1c6590d4bb5fd80a8d23c95ea643a Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 16 May 2023 11:05:29 +0100 Subject: [PATCH 038/178] Revert "Make Resources folder for emoji font mod" This reverts commit 00c9bd2e55302660683803d09cec42ac35ace746. --- .gitmodules | 3 --- Resources/Mods/rbxcustom-fontemojis | 1 - 2 files changed, 4 deletions(-) delete mode 160000 Resources/Mods/rbxcustom-fontemojis diff --git a/.gitmodules b/.gitmodules index 05601267..1b06faef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "wpfui"] path = wpfui url = https://github.com/pizzaboxer/wpfui.git -[submodule "Resources/Mods/rbxcustom-fontemojis"] - path = Resources/Mods/rbxcustom-fontemojis - url = https://github.com/NikSavchenk0/rbxcustom-fontemojis diff --git a/Resources/Mods/rbxcustom-fontemojis b/Resources/Mods/rbxcustom-fontemojis deleted file mode 160000 index 8a552f4a..00000000 --- a/Resources/Mods/rbxcustom-fontemojis +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8a552f4aaaecfa58d6bd9b0540e1ac16e81faadb From 5d94ca7944c6d7ffeb7bbc7af16f273cd05ec325 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 16 May 2023 11:05:33 +0100 Subject: [PATCH 039/178] Revert "Update ci.yml" This reverts commit 50bb408e188ad1881fa8fa3d3b96664c33d45acb. --- .github/workflows/ci.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d3ab1f7..1921310c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,6 @@ name: CI -on: - push: - paths-ignore: - - 'Resources/**' - pull_request: - paths-ignore: - - 'Resources/**' - +on: [push, pull_request] + jobs: build: strategy: From a740f99b509242bba4d894f0345ca773b868f9ae Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 18 May 2023 11:24:09 +0100 Subject: [PATCH 040/178] Add support for emoij selection (#148) --- Bloxstrap/Bootstrapper.cs | 25 ++++++++++++++ Bloxstrap/Enums/EmojiType.cs | 11 ++++++ Bloxstrap/Extensions/EmojiTypeEx.cs | 34 +++++++++++++++++++ Bloxstrap/Models/Settings.cs | 1 + Bloxstrap/Models/State.cs | 3 ++ Bloxstrap/UI/Menu/ViewModels/ModsViewModel.cs | 14 +++++++- Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml | 11 ++++++ 7 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 Bloxstrap/Enums/EmojiType.cs create mode 100644 Bloxstrap/Extensions/EmojiTypeEx.cs diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 75f27aed..851642ce 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -13,6 +13,7 @@ using Microsoft.Win32; using Bloxstrap.Enums; +using Bloxstrap.Extensions; using Bloxstrap.Integrations; using Bloxstrap.Models; using Bloxstrap.Tools; @@ -915,6 +916,30 @@ private async Task ApplyModifications() await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseDisableAppPatch, @"ExtraContent\places\Mobile.rbxl", ""); + // emoji presets are downloaded remotely from github due to how large they are + string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); + + if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + App.State.Prop.CurrentEmojiType = EmojiType.Default; + } + else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); + + var response = await App.HttpClient.GetAsync(remoteEmojiLocation); + await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + + App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; + } + foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) { // get relative directory path diff --git a/Bloxstrap/Enums/EmojiType.cs b/Bloxstrap/Enums/EmojiType.cs new file mode 100644 index 00000000..cdefefd5 --- /dev/null +++ b/Bloxstrap/Enums/EmojiType.cs @@ -0,0 +1,11 @@ +namespace Bloxstrap.Enums +{ + public enum EmojiType + { + Default, + Catmoji, + Windows11, + Windows10, + Windows8 + } +} diff --git a/Bloxstrap/Extensions/EmojiTypeEx.cs b/Bloxstrap/Extensions/EmojiTypeEx.cs new file mode 100644 index 00000000..5978b661 --- /dev/null +++ b/Bloxstrap/Extensions/EmojiTypeEx.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +using Bloxstrap.Enums; + +namespace Bloxstrap.Extensions +{ + static class EmojiTypeEx + { + public static IReadOnlyDictionary Selections => new Dictionary + { + { "Default (Twemoji)", EmojiType.Default }, + { "Catmoji", EmojiType.Catmoji }, + { "Windows 11", EmojiType.Windows11 }, + { "Windows 10", EmojiType.Windows10 }, + { "Windows 8", EmojiType.Windows8 }, + }; + + public static IReadOnlyDictionary Filenames => new Dictionary + { + { EmojiType.Catmoji, "Catmoji.ttf" }, + { EmojiType.Windows11, "Win1122H2SegoeUIEmoji.ttf" }, + { EmojiType.Windows10, "Win10April2018SegoeUIEmoji.ttf" }, + { EmojiType.Windows8, "Win8.1SegoeUIEmoji.ttf" }, + }; + + public static string GetRemoteLocation(this EmojiType emojiType) + { + if (emojiType == EmojiType.Default) + return ""; + + return $"https://github.com/NikSavchenk0/rbxcustom-fontemojis/raw/8a552f4aaaecfa58d6bd9b0540e1ac16e81faadb/{Filenames[emojiType]}"; + } + } +} diff --git a/Bloxstrap/Models/Settings.cs b/Bloxstrap/Models/Settings.cs index cfb173f3..477d324c 100644 --- a/Bloxstrap/Models/Settings.cs +++ b/Bloxstrap/Models/Settings.cs @@ -31,6 +31,7 @@ public class Settings public bool UseOldCharacterSounds { get; set; } = false; public bool UseOldMouseCursor { get; set; } = false; public bool UseDisableAppPatch { get; set; } = false; + public EmojiType PreferredEmojiType { get; set; } = EmojiType.Default; public bool DisableFullscreenOptimizations { get; set; } = false; } } diff --git a/Bloxstrap/Models/State.cs b/Bloxstrap/Models/State.cs index 5b59a9bb..cd1a7fcf 100644 --- a/Bloxstrap/Models/State.cs +++ b/Bloxstrap/Models/State.cs @@ -1,10 +1,13 @@ using System.Collections.Generic; +using Bloxstrap.Enums; + namespace Bloxstrap.Models { public class State { public string VersionGuid { get; set; } = ""; + public EmojiType CurrentEmojiType { get; set; } = EmojiType.Default; public List ModManifest { get; set; } = new(); } } diff --git a/Bloxstrap/UI/Menu/ViewModels/ModsViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/ModsViewModel.cs index 9be11018..e9117a12 100644 --- a/Bloxstrap/UI/Menu/ViewModels/ModsViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/ModsViewModel.cs @@ -1,7 +1,11 @@ -using System.ComponentModel; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Windows.Input; +using Bloxstrap.Enums; +using Bloxstrap.Extensions; + using CommunityToolkit.Mvvm.Input; namespace Bloxstrap.UI.Menu.ViewModels @@ -36,6 +40,14 @@ public bool DisableAppPatchEnabled set => App.Settings.Prop.UseDisableAppPatch = value; } + public IReadOnlyDictionary EmojiTypes => EmojiTypeEx.Selections; + + public string SelectedEmojiType + { + get => EmojiTypes.FirstOrDefault(x => x.Value == App.Settings.Prop.PreferredEmojiType).Key; + set => App.Settings.Prop.PreferredEmojiType = EmojiTypes[value]; + } + public bool DisableFullscreenOptimizationsEnabled { get => App.Settings.Prop.DisableFullscreenOptimizations; diff --git a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml index 8d0e4f19..57dd470e 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml @@ -63,6 +63,7 @@ + @@ -107,6 +108,16 @@ + + + + + + + + + + From af26604980d115bbf39864d201fce048bb745803 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 18 May 2023 20:46:06 +0100 Subject: [PATCH 041/178] oh yeah some more stuff --- Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml index c423ae96..2a6f0bc7 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml @@ -37,7 +37,8 @@ - + + @@ -54,6 +55,7 @@ + @@ -96,14 +98,19 @@ - EasternBloxxer + NikSavchenk0 - + + EasternBloxxer + + + + carter0nline - + From c7a7feeebfffd8131d368cdbc6253495ca5dc673 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 24 May 2023 11:02:57 +0100 Subject: [PATCH 042/178] Add process ID to log filename #212 an attempt to mitigate a bug with rogold accidentally launching roblox twice when launching a game through one of its added features making bloxstrap error because both instances will have the same log filename don't want to just terminate any launched instances that encounter the same filename since there could be a case of someone intentionally launching roblox repeatedly this won't actually stop the double launching, there's not much way around that without being able to see the executing args of other bloxstrap instances, but it solves the error --- Bloxstrap/App.xaml.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 34a229c5..2dc51abd 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -80,8 +80,9 @@ private void InitLog() bool isUsingTempDir = IsFirstRun || IsUninstall; string logdir = isUsingTempDir ? Path.Combine(Directories.LocalAppData, "Temp") : Path.Combine(Directories.Base, "Logs"); string timestamp = DateTime.UtcNow.ToString("yyyyMMdd'T'HHmmss'Z'"); + int processId = Process.GetCurrentProcess().Id; - Logger.Initialize(Path.Combine(logdir, $"{ProjectName}_{timestamp}.log")); + Logger.Initialize(Path.Combine(logdir, $"{ProjectName}_{timestamp}_{processId}.log")); // clean up any logs older than a week if (!isUsingTempDir) From 54b65f87283ba223e27dbaad00fc32d41b2a6d25 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 24 May 2023 11:21:53 +0100 Subject: [PATCH 043/178] Improve WebView2 install handling cuts down on code and should better account for multiple instances --- Bloxstrap/Bootstrapper.cs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 851642ce..06dfbc23 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -73,7 +73,6 @@ public class Bootstrapper private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); - private static bool ShouldInstallWebView2 = false; private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); @@ -96,15 +95,6 @@ public class Bootstrapper public Bootstrapper(string launchCommandLine) { _launchCommandLine = launchCommandLine; - - // check if the webview2 runtime needs to be installed - // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu - // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed - - string hklmLocation = "SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"; - string hkcuLocation = "Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"; - - ShouldInstallWebView2 = Registry.LocalMachine.OpenSubKey(hklmLocation) is null && Registry.CurrentUser.OpenSubKey(hkcuLocation) is null; } private void SetStatus(string message) @@ -192,8 +182,7 @@ public async Task Run() MigrateIntegrations(); - if (ShouldInstallWebView2) - await InstallWebView2(); + await InstallWebView2(); App.FastFlags.Save(); await ApplyModifications(); @@ -804,7 +793,14 @@ private async Task InstallLatestVersion() private async Task InstallWebView2() { - if (!ShouldInstallWebView2) + // check if the webview2 runtime needs to be installed + // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu + // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed + + using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + using RegistryKey? hkcuKey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + + if (hklmKey is not null || hkcuKey is not null) return; App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); From 57e6454fd7153a7f6995ea11522481a7dea609ce Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 24 May 2023 14:56:47 +0100 Subject: [PATCH 044/178] Add program size estimation conditions are kinda messy but its fine --- Bloxstrap/Bootstrapper.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 06dfbc23..ab22d148 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -188,7 +188,10 @@ public async Task Run() await ApplyModifications(); if (App.IsFirstRun || FreshInstall) + { Register(); + RegisterProgramSize(); + } CheckInstall(); @@ -425,6 +428,20 @@ public static void Register() App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); } + public void RegisterProgramSize() + { + App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); + + using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); + + // sum compressed and uncompressed package sizes and convert to kilobytes + int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; + + uninstallKey.SetValue("EstimatedSize", totalSize); + + App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); + } + private void CheckInstallMigration() { // check if we've changed our install location since the last time we started @@ -785,6 +802,10 @@ private async Task InstallLatestVersion() App.State.Prop.VersionGuid = _latestVersionGuid; + // don't register program size until the program is registered + if (!App.IsFirstRun && !FreshInstall) + RegisterProgramSize(); + if (Dialog is not null) Dialog.CancelEnabled = false; From 244c3dee40bef7147440ccc1ae6fdee8af0b73fd Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 24 May 2023 18:27:11 +0100 Subject: [PATCH 045/178] Fully cleanup Bloxstrap folder after install this also goes to show just how much of a mess bootstrapper dialog management is lol --- Bloxstrap/Bootstrapper.cs | 22 ++++++++++++++++++- .../IBootstrapperDialog.cs | 5 +++-- .../WPF/Views/ByfronDialog.xaml.cs | 6 ++++- .../WPF/Views/FluentDialog.xaml.cs | 6 ++++- .../WinForms/DialogBase.cs | 6 ++++- .../WinForms/VistaDialog.cs | 12 +++++++--- 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index ab22d148..55c60466 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -688,7 +688,27 @@ private void Uninstall() App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); } - Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled"); + Action? callback = null; + + if (Directory.Exists(Directories.Base)) + { + callback = () => + { + // this is definitely one of the workaround hacks of all time + // could antiviruses falsely detect this as malicious behaviour though? + // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" + + Process.Start(new ProcessStartInfo() + { + FileName = "cmd.exe", + Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", + UseShellExecute = true, + WindowStyle = ProcessWindowStyle.Hidden + }); + }; + } + + Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); } #endregion diff --git a/Bloxstrap/UI/BootstrapperDialogs/IBootstrapperDialog.cs b/Bloxstrap/UI/BootstrapperDialogs/IBootstrapperDialog.cs index 0531c1e0..5b36844a 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/IBootstrapperDialog.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/IBootstrapperDialog.cs @@ -1,4 +1,5 @@ -using System.Windows.Forms; +using System; +using System.Windows.Forms; namespace Bloxstrap.UI.BootstrapperDialogs { @@ -13,7 +14,7 @@ public interface IBootstrapperDialog void ShowBootstrapper(); void CloseBootstrapper(); - void ShowSuccess(string message); + void ShowSuccess(string message, Action? callback = null); void ShowError(string message); void PromptShutdown(); } diff --git a/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/ByfronDialog.xaml.cs b/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/ByfronDialog.xaml.cs index 200327de..76c8c0c2 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/ByfronDialog.xaml.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/ByfronDialog.xaml.cs @@ -91,9 +91,13 @@ public ByfronDialog() public void CloseBootstrapper() => Dispatcher.BeginInvoke(this.Close); - public void ShowSuccess(string message) + public void ShowSuccess(string message, Action? callback) { App.ShowMessageBox(message, MessageBoxImage.Information); + + if (callback is not null) + callback(); + App.Terminate(); } diff --git a/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/FluentDialog.xaml.cs b/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/FluentDialog.xaml.cs index 052d7baa..559a2ab1 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/FluentDialog.xaml.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/WPF/Views/FluentDialog.xaml.cs @@ -85,9 +85,13 @@ public FluentDialog() // TODO: make prompts use dialog view natively rather than using message dialog boxes - public void ShowSuccess(string message) + public void ShowSuccess(string message, Action? callback) { App.ShowMessageBox(message, MessageBoxImage.Information); + + if (callback is not null) + callback(); + App.Terminate(); } diff --git a/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs b/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs index 3bec0eb5..dfcc15ec 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs @@ -99,9 +99,13 @@ public virtual void CloseBootstrapper() Close(); } - public virtual void ShowSuccess(string message) + public virtual void ShowSuccess(string message, Action? callback) { App.ShowMessageBox(message, MessageBoxImage.Information); + + if (callback is not null) + callback(); + App.Terminate(); } diff --git a/Bloxstrap/UI/BootstrapperDialogs/WinForms/VistaDialog.cs b/Bloxstrap/UI/BootstrapperDialogs/WinForms/VistaDialog.cs index d2111010..211036f9 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/WinForms/VistaDialog.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/WinForms/VistaDialog.cs @@ -80,11 +80,11 @@ public VistaDialog() SetupDialog(); } - public override void ShowSuccess(string message) + public override void ShowSuccess(string message, Action? callback) { if (this.InvokeRequired) { - this.Invoke(ShowSuccess, message); + this.Invoke(ShowSuccess, message, callback); } else { @@ -96,7 +96,13 @@ public override void ShowSuccess(string message) Buttons = { TaskDialogButton.OK } }; - successDialog.Buttons[0].Click += (_, _) => App.Terminate(); + successDialog.Buttons[0].Click += (_, _) => + { + if (callback is not null) + callback(); + + App.Terminate(); + }; _dialogPage.Navigate(successDialog); _dialogPage = successDialog; From ada0dc91af555da1228d28d68a1817d248f7fedc Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 25 May 2023 22:56:08 +0100 Subject: [PATCH 046/178] Better handling of malformed registry key (#264) --- Bloxstrap/App.xaml.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 2dc51abd..9e39d45c 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -174,7 +174,12 @@ protected override void OnStartup(StartupEventArgs e) // check if installed using (RegistryKey? registryKey = Registry.CurrentUser.OpenSubKey($@"Software\{ProjectName}")) { - if (registryKey is null) + string? installLocation = null; + + if (registryKey is not null) + installLocation = (string?)registryKey.GetValue("InstallLocation"); + + if (registryKey is null || installLocation is null) { Logger.WriteLine("[App::OnStartup] Running first-time install"); @@ -191,7 +196,7 @@ protected override void OnStartup(StartupEventArgs e) else { IsFirstRun = false; - BaseDirectory = (string)registryKey.GetValue("InstallLocation")!; + BaseDirectory = installLocation; } } From c1410aa38ce38323fc46594d48dce6cabe6ad0c3 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 25 May 2023 23:02:53 +0100 Subject: [PATCH 047/178] Add option for FIB Phase 2 / ShadowMap (#263) --- Bloxstrap/Singletons/FastFlagManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index 7c5d8391..0b2a7a4e 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -32,7 +32,8 @@ public class FastFlagManager : JsonManager> { { "Automatic", "" }, { "Voxel", "DFFlagDebugRenderForceTechnologyVoxel" }, - { "Future Is Bright", "FFlagDebugForceFutureIsBrightPhase3" } + { "ShadowMap", "FFlagDebugForceFutureIsBrightPhase2" }, + { "Future", "FFlagDebugForceFutureIsBrightPhase3" } }; // this is one hell of a variable definition lmao From 1106d1ff0cfca1f8b07dc36dcb8a7bfa521d6afa Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 25 May 2023 23:09:29 +0100 Subject: [PATCH 048/178] Rearrange FastFlags menu tab prioritized presets that are likely to be used the most, and are what would stand out to people the most also removed the desktop app mobile layout preset, primarily just added it for filler when i was first working on fflag integration but now there really is too many options lol --- .../UI/Menu/ViewModels/FastFlagsViewModel.cs | 6 --- .../UI/Menu/Views/Pages/FastFlagsPage.xaml | 49 ++++++++----------- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs index b4a175f7..d5ccc5e8 100644 --- a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs @@ -142,11 +142,5 @@ public bool GuiHidingEnabled get => App.FastFlags.GetValue("DFIntCanHideGuiGroupId") == "32380007"; set => App.FastFlags.SetValue("DFIntCanHideGuiGroupId", value ? "32380007" : null); } - - public bool MobileLuaAppInterfaceEnabled - { - get => App.FastFlags.GetValue("FFlagLuaAppSystemBar") == "False"; - set => App.FastFlags.SetValue("FFlagLuaAppSystemBar", value ? "False" : null); - } } } diff --git a/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml index ec608b75..5977714d 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml @@ -54,29 +54,31 @@ - - + + - + - - + + - + - - + + + TODO - add text for wiki page for controls when done. You must be in the Bloxstrap group for it to work. + - + @@ -90,40 +92,29 @@ - - - - - - - - - - - + + - + - - - TODO - add text for wiki page for controls when done. You must be in the Bloxstrap group for it to work. - + + - + - - + + - + From 053197ca64dc247dc0a23f3449fd702596e87b14 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 25 May 2023 23:13:36 +0100 Subject: [PATCH 049/178] Fix spacing --- Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml | 2 +- Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml b/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml index ceff752f..b5b2c4ca 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml @@ -12,7 +12,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml index 4ada6118..e0d7ff41 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml @@ -11,7 +11,7 @@ - + From cf1514d6be6d0d9963984b595240d1dc1db07bc3 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 27 May 2023 19:25:33 +0100 Subject: [PATCH 050/178] Use ToLowerInvariant() instead of ToLower() (#268) oops --- Bloxstrap/Bootstrapper.cs | 6 +++--- Bloxstrap/ProtocolHandler.cs | 2 +- Bloxstrap/RobloxDeployment.cs | 4 ++-- Bloxstrap/ViewModels/InstallationViewModel.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 9ecfb0d2..6392216a 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -219,7 +219,7 @@ private async Task CheckLatestVersion() ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); // briefly check if current channel is suitable to use - if (App.Settings.Prop.Channel.ToLower() != RobloxDeployment.DefaultChannel.ToLower() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) { string? switchDefaultPrompt = null; ClientVersion? defaultChannelInfo = null; @@ -272,8 +272,8 @@ private async Task StartRoblox() _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); - if (App.Settings.Prop.Channel.ToLower() != RobloxDeployment.DefaultChannel.ToLower()) - _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLower(); + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) + _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes bool shouldWait = false; diff --git a/Bloxstrap/ProtocolHandler.cs b/Bloxstrap/ProtocolHandler.cs index ffae5e5d..a186c93e 100644 --- a/Bloxstrap/ProtocolHandler.cs +++ b/Bloxstrap/ProtocolHandler.cs @@ -57,7 +57,7 @@ public static string ParseUri(string protocol) if (key == "channel") { - if (val.ToLower() != App.Settings.Prop.Channel.ToLower() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) + if (val.ToLowerInvariant() != App.Settings.Prop.Channel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) { MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox( $"{App.ProjectName} was launched with the Roblox build channel set to {val}, however your current preferred channel is {App.Settings.Prop.Channel}.\n\n" + diff --git a/Bloxstrap/RobloxDeployment.cs b/Bloxstrap/RobloxDeployment.cs index ed865c87..69390ccf 100644 --- a/Bloxstrap/RobloxDeployment.cs +++ b/Bloxstrap/RobloxDeployment.cs @@ -78,8 +78,8 @@ public static string GetLocation(string resource, string? channel = null) string location = BaseUrl; - if (channel.ToLower() != DefaultChannel.ToLower()) - location += $"/channel/{channel.ToLower()}"; + if (channel.ToLowerInvariant() != DefaultChannel.ToLowerInvariant()) + location += $"/channel/{channel.ToLowerInvariant()}"; location += resource; diff --git a/Bloxstrap/ViewModels/InstallationViewModel.cs b/Bloxstrap/ViewModels/InstallationViewModel.cs index 7eca88e5..ded5f5b3 100644 --- a/Bloxstrap/ViewModels/InstallationViewModel.cs +++ b/Bloxstrap/ViewModels/InstallationViewModel.cs @@ -104,7 +104,7 @@ public bool ManualChannelEntry if (!value) { // roblox typically sets channels in all lowercase, so here we find if a case insensitive match exists - string? matchingChannel = Channels.Where(x => x.ToLower() == Channel.ToLower()).FirstOrDefault(); + string? matchingChannel = Channels.Where(x => x.ToLowerInvariant() == Channel.ToLowerInvariant()).FirstOrDefault(); Channel = String.IsNullOrEmpty(matchingChannel) ? RobloxDeployment.DefaultChannel : matchingChannel; } From 778a67dcb93c5537da5d78b6287eaca15e920ecf Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 12 Jun 2023 11:41:24 +0100 Subject: [PATCH 051/178] Add support for the 2023 v4 menu --- Bloxstrap/Properties/launchSettings.json | 4 +++ Bloxstrap/Singletons/FastFlagManager.cs | 35 ++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Bloxstrap/Properties/launchSettings.json b/Bloxstrap/Properties/launchSettings.json index 63472e59..ee3606b7 100644 --- a/Bloxstrap/Properties/launchSettings.json +++ b/Bloxstrap/Properties/launchSettings.json @@ -18,6 +18,10 @@ "Bloxstrap (Menu)": { "commandName": "Project", "commandLineArgs": "-menu" + }, + "Bloxstrap (Deeplink)": { + "commandName": "Project", + "commandLineArgs": "roblox://experiences/start?placeId=95206881" } } } \ No newline at end of file diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index 0b2a7a4e..191c645c 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -36,7 +36,8 @@ public class FastFlagManager : JsonManager> { "Future", "FFlagDebugForceFutureIsBrightPhase3" } }; - // this is one hell of a variable definition lmao + // this is one hell of a dictionary definition lmao + // since these all set the same flags, wouldn't making this use bitwise operators be better? public static IReadOnlyDictionary> IGMenuVersions => new Dictionary> { { @@ -44,7 +45,10 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", null }, - { "FFlagEnableInGameMenuV3", null } + { "FFlagEnableInGameMenuV3", null }, + { "FFlagEnableInGameMenuControls", null }, + { "FFlagEnableV3MenuABTest3", null }, + { "FFlagEnableMenuControlsABTest", null } } }, @@ -53,7 +57,10 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", "True" }, - { "FFlagEnableInGameMenuV3", "False" } + { "FFlagEnableInGameMenuV3", "False" }, + { "FFlagEnableInGameMenuControls", "False" }, + { "FFlagEnableV3MenuABTest3", "False" }, + { "FFlagEnableMenuControlsABTest", "False" } } }, @@ -62,7 +69,10 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", "False" }, - { "FFlagEnableInGameMenuV3", "False" } + { "FFlagEnableInGameMenuV3", "False" }, + { "FFlagEnableInGameMenuControls", "False" }, + { "FFlagEnableV3MenuABTest3", "False" }, + { "FFlagEnableMenuControlsABTest", "False" } } }, @@ -71,7 +81,22 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", "False" }, - { "FFlagEnableInGameMenuV3", "True" } + { "FFlagEnableInGameMenuV3", "True" }, + { "FFlagEnableInGameMenuControls", "False" }, + { "FFlagEnableV3MenuABTest3", "False" }, + { "FFlagEnableMenuControlsABTest", "False" } + } + }, + + { + "Version 4 (2023)", + new Dictionary + { + { "FFlagDisableNewIGMinDUA", "True" }, + { "FFlagEnableInGameMenuV3", "False" }, + { "FFlagEnableInGameMenuControls", "True" }, + { "FFlagEnableV3MenuABTest3", "True" }, + { "FFlagEnableMenuControlsABTest", "True" } } } }; From 3926f308668583a0829f34efcde57a334f9465de Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 12 Jun 2023 12:16:42 +0100 Subject: [PATCH 052/178] Improve how multiple menu instances are handled --- Bloxstrap/App.xaml.cs | 23 ++++++++++------------- Bloxstrap/NativeMethods.cs | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 Bloxstrap/NativeMethods.cs diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 9e39d45c..a16478df 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -228,24 +228,21 @@ protected override void OnStartup(StartupEventArgs e) if (IsMenuLaunch) { - Mutex mutex; + Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault(); - try + if (menuProcess is not null) { - mutex = Mutex.OpenExisting("Bloxstrap_MenuMutex"); - Logger.WriteLine("[App::OnStartup] Bloxstrap_MenuMutex mutex exists, aborting menu launch..."); - Terminate(); + IntPtr handle = menuProcess.MainWindowHandle; + Logger.WriteLine($"[App::OnStartup] Found an already existing menu window with handle {handle}"); + NativeMethods.SetForegroundWindow(handle); } - catch + else { - // no mutex exists, continue to opening preferences menu - mutex = new(true, "Bloxstrap_MenuMutex"); - } + if (Process.GetProcessesByName(ProjectName).Length > 1) + ShowMessageBox($"{ProjectName} is currently running, likely as a background Roblox process. Please note that not all your changes will immediately apply until you close all currently open Roblox instances.", MessageBoxImage.Information); - if (Utilities.GetProcessCount(ProjectName) > 1) - ShowMessageBox($"{ProjectName} is currently running, likely as a background Roblox process. Please note that not all your changes will immediately apply until you close all currently open Roblox instances.", MessageBoxImage.Information); - - new MainWindow().ShowDialog(); + new MainWindow().ShowDialog(); + } } else if (LaunchArgs.Length > 0) { diff --git a/Bloxstrap/NativeMethods.cs b/Bloxstrap/NativeMethods.cs new file mode 100644 index 00000000..7cf69810 --- /dev/null +++ b/Bloxstrap/NativeMethods.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap +{ + static class NativeMethods + { + [DllImport("user32.dll")] + public static extern bool SetForegroundWindow(IntPtr hWnd); + } +} From 09ad91623643bd6b7b069980d2c0f65912ac8df3 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 12 Jun 2023 16:49:14 +0100 Subject: [PATCH 053/178] Improve how updating Roblox is handled fixes the problem of the versions folder not being properly cleaned out also instead of skipping the roblox update process if multiple instances are running, continue with the update process but don't delete any older versions when finished --- Bloxstrap/App.xaml.cs | 1 + Bloxstrap/Bootstrapper.cs | 34 +++++++++++++++++++--------------- Bloxstrap/Singletons/Logger.cs | 5 +++++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index a16478df..d49ad31c 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -30,6 +30,7 @@ public partial class App : Application public const string ProjectName = "Bloxstrap"; public const string ProjectRepository = "pizzaboxer/bloxstrap"; + public const string RobloxAppName = "RobloxPlayerBeta"; // used only for communicating between app and menu - use Directories.Base for anything else public static string BaseDirectory = null!; diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 3da54e13..7cf2a02d 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -168,15 +168,10 @@ public async Task Run() CheckInstallMigration(); - // only update roblox if we're running for the first time, or if - // roblox isn't running and our version guid is out of date, or the player exe doesn't exist - if (App.IsFirstRun || !Utilities.CheckIfRobloxRunning() && (_latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation))) + // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist + if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) await InstallLatestVersion(); - // last time the version folder was set, it was set to the latest version guid - // but if we skipped updating because roblox is already running, we want it to be set to our current version - _versionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); - if (App.IsFirstRun) App.ShouldSaveConfigs = true; @@ -792,19 +787,13 @@ private async Task InstallLatestVersion() { if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) { - App.Logger.WriteLine($"Deleting unused package {filename}"); + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); File.Delete(filename); } } string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); - if (_latestVersionGuid != App.State.Prop.VersionGuid && Directory.Exists(oldVersionFolder)) - { - // and also to delete our old version folder - Directory.Delete(oldVersionFolder, true); - } - // move old compatibility flags for the old location using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) { @@ -817,12 +806,27 @@ private async Task InstallLatestVersion() appFlagsKey.SetValue(_playerLocation, appFlags); appFlagsKey.DeleteValue(oldGameClientLocation); } + } + + // delete any old version folders + // we only do this if roblox isnt running just in case an update happened + // while they were launching a second instance or something idk + if (!Process.GetProcessesByName(App.RobloxAppName).Any()) + { + foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) + { + if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) + continue; + + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); + dir.Delete(true); + } } } App.State.Prop.VersionGuid = _latestVersionGuid; - // don't register program size until the program is registered + // don't register program size until the program is registered, which will be done after this if (!App.IsFirstRun && !FreshInstall) RegisterProgramSize(); diff --git a/Bloxstrap/Singletons/Logger.cs b/Bloxstrap/Singletons/Logger.cs index 97a53503..190f8b5d 100644 --- a/Bloxstrap/Singletons/Logger.cs +++ b/Bloxstrap/Singletons/Logger.cs @@ -8,6 +8,11 @@ namespace Bloxstrap.Singletons { // https://stackoverflow.com/a/53873141/11852173 + // TODO - this kind of sucks + // the main problem is just that this doesn't finish writing log entries before exiting the program + // this can be solved by making writetolog completely synchronous, but while it doesn't affect performance, its's not ideal + // also, writing and flushing for every single line that's written may not be great + public class Logger { private readonly SemaphoreSlim _semaphore = new(1, 1); From a71f8e5606f3f2c19adf96e3ea3c6ca74446d5b8 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 13 Jun 2023 08:12:16 +0100 Subject: [PATCH 054/178] WebView2 bugfix oops lol --- Bloxstrap/Bootstrapper.cs | 2438 ++++++++++++++++++------------------- 1 file changed, 1219 insertions(+), 1219 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 7cf2a02d..7c5059b5 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1,1224 +1,1224 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using System.Windows; - -using Microsoft.Win32; - -using Bloxstrap.Enums; -using Bloxstrap.Extensions; -using Bloxstrap.Integrations; -using Bloxstrap.Models; -using Bloxstrap.Tools; -using Bloxstrap.UI.BootstrapperDialogs; - -namespace Bloxstrap -{ - public class Bootstrapper - { - #region Properties - - // https://learn.microsoft.com/en-us/windows/win32/msi/error-codes - public const int ERROR_SUCCESS = 0; - public const int ERROR_INSTALL_USEREXIT = 1602; - public const int ERROR_INSTALL_FAILURE = 1603; - - // in case a new package is added, you can find the corresponding directory - // by opening the stock bootstrapper in a hex editor - // TODO - there ideally should be a less static way to do this that's not hardcoded? - private static readonly IReadOnlyDictionary PackageDirectories = new Dictionary() - { - { "RobloxApp.zip", @"" }, - { "shaders.zip", @"shaders\" }, - { "ssl.zip", @"ssl\" }, - - // the runtime installer is only extracted if it needs installing - { "WebView2.zip", @"" }, - { "WebView2RuntimeInstaller.zip", @"WebView2RuntimeInstaller\" }, - - { "content-avatar.zip", @"content\avatar\" }, - { "content-configs.zip", @"content\configs\" }, - { "content-fonts.zip", @"content\fonts\" }, - { "content-sky.zip", @"content\sky\" }, - { "content-sounds.zip", @"content\sounds\" }, - { "content-textures2.zip", @"content\textures\" }, - { "content-models.zip", @"content\models\" }, - - { "content-textures3.zip", @"PlatformContent\pc\textures\" }, - { "content-terrain.zip", @"PlatformContent\pc\terrain\" }, - { "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" }, - - { "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" }, - { "extracontent-translations.zip", @"ExtraContent\translations\" }, - { "extracontent-models.zip", @"ExtraContent\models\" }, - { "extracontent-textures.zip", @"ExtraContent\textures\" }, - { "extracontent-places.zip", @"ExtraContent\places\" }, - }; - - private const string AppSettings = - "\r\n" + - "\r\n" + - " content\r\n" + - " http://www.roblox.com\r\n" + - "\r\n"; - - private readonly CancellationTokenSource _cancelTokenSource = new(); - - private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); - private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); - - private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); - - private string _launchCommandLine; - - private string _latestVersionGuid = null!; - private PackageManifest _versionPackageManifest = null!; - private string _versionFolder = null!; - - private bool _isInstalling = false; - private double _progressIncrement; - private long _totalDownloadedBytes = 0; - private int _packagesExtracted = 0; - private bool _cancelFired = false; - - public IBootstrapperDialog? Dialog = null; - #endregion - - #region Core - public Bootstrapper(string launchCommandLine) - { - _launchCommandLine = launchCommandLine; - } - - private void SetStatus(string message) - { - App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); - - // yea idk - if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) - message = message.Replace("...", ""); - - if (Dialog is not null) - Dialog.Message = message; - } - - private void UpdateProgressbar() - { - int newProgress = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes); - - // bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100 - // too lazy to fix properly so lol - if (newProgress > 100) - return; - - if (Dialog is not null) - Dialog.ProgressValue = newProgress; - } - - public async Task Run() - { - App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); - - if (App.IsUninstall) - { - Uninstall(); - return; - } - -#if !DEBUG - if (!App.IsFirstRun && App.Settings.Prop.CheckForUpdates) - await CheckForUpdates(); -#endif - - // ensure only one instance of the bootstrapper is running at the time - // so that we don't have stuff like two updates happening simultaneously - - bool mutexExists = false; - - try - { - Mutex.OpenExisting("Bloxstrap_BootstrapperMutex").Close(); - App.Logger.WriteLine("[Bootstrapper::Run] Bloxstrap_BootstrapperMutex mutex exists, waiting..."); - mutexExists = true; - } - catch (Exception) - { - // no mutex exists - } - - // wait for mutex to be released if it's not yet - await using AsyncMutex mutex = new("Bloxstrap_BootstrapperMutex"); - await mutex.AcquireAsync(_cancelTokenSource.Token); - - // reload our configs since they've likely changed by now - if (mutexExists) - { - App.Settings.Load(); - App.State.Load(); - } - - await CheckLatestVersion(); - - CheckInstallMigration(); - - // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist - if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) - await InstallLatestVersion(); - - if (App.IsFirstRun) - App.ShouldSaveConfigs = true; - - MigrateIntegrations(); - - await InstallWebView2(); - - App.FastFlags.Save(); - await ApplyModifications(); - - if (App.IsFirstRun || FreshInstall) - { - Register(); - RegisterProgramSize(); - } - - CheckInstall(); - - // at this point we've finished updating our configs - App.Settings.Save(); - App.State.Save(); - App.ShouldSaveConfigs = false; - - await mutex.ReleaseAsync(); - - if (App.IsFirstRun && App.IsNoLaunch) - Dialog?.ShowSuccess($"{App.ProjectName} has successfully installed"); - else if (!App.IsNoLaunch && !_cancelFired) - await StartRoblox(); - } - - private async Task CheckLatestVersion() - { - SetStatus("Connecting to Roblox..."); - - ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); - - // briefly check if current channel is suitable to use - if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) - { - string? switchDefaultPrompt = null; - ClientVersion? defaultChannelInfo = null; - - App.Logger.WriteLine($"[Bootstrapper::CheckLatestVersion] Checking if current channel is suitable to use..."); - - if (String.IsNullOrEmpty(switchDefaultPrompt)) - { - // this SUCKS - defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); - int defaultChannelVersion = Int32.Parse(defaultChannelInfo.Version.Split('.')[1]); - int currentChannelVersion = Int32.Parse(clientVersion.Version.Split('.')[1]); - - if (currentChannelVersion < defaultChannelVersion) - switchDefaultPrompt = $"Your current preferred channel ({App.Settings.Prop.Channel}) appears to no longer be receiving updates. Would you like to switch to {RobloxDeployment.DefaultChannel}?"; - } - - if (!String.IsNullOrEmpty(switchDefaultPrompt)) - { - MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox(switchDefaultPrompt, MessageBoxImage.Question, MessageBoxButton.YesNo); - - if (result == MessageBoxResult.Yes) - { - App.Settings.Prop.Channel = RobloxDeployment.DefaultChannel; - App.Logger.WriteLine($"[DeployManager::SwitchToDefault] Changed Roblox release channel from {App.Settings.Prop.Channel} to {RobloxDeployment.DefaultChannel}"); - - if (defaultChannelInfo is null) - defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); - - clientVersion = defaultChannelInfo; - } - } - } - - _latestVersionGuid = clientVersion.VersionGuid; - _versionFolder = Path.Combine(Directories.Versions, _latestVersionGuid); - _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); - } - - private async Task StartRoblox() - { - SetStatus("Starting Roblox..."); - - if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) - { - Utilities.OpenWebsite("https://www.roblox.com/games"); - Dialog?.CloseBootstrapper(); - return; - } - - _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); - - if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) - _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); - - // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes - bool shouldWait = false; - - // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now - int gameClientPid; - using (Process gameClient = Process.Start(_playerLocation, _launchCommandLine)) - { - gameClientPid = gameClient.Id; - } - - List autocloseProcesses = new(); - RobloxActivity? activityWatcher = null; - DiscordRichPresence? richPresence = null; - ServerNotifier? serverNotifier = null; - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Started Roblox (PID {gameClientPid})"); - - using (SystemEvent startEvent = new("www.roblox.com/robloxStartedEvent")) - { - bool startEventFired = await startEvent.WaitForEvent(); - - startEvent.Close(); - - if (!startEventFired) - return; - } - - if (App.Settings.Prop.UseDiscordRichPresence || App.Settings.Prop.ShowServerDetails) - { - activityWatcher = new(); - shouldWait = true; - } - - if (App.Settings.Prop.UseDiscordRichPresence) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); - richPresence = new(activityWatcher!); - } - - if (App.Settings.Prop.ShowServerDetails) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using server details notifier"); - serverNotifier = new(activityWatcher!); - } - - // launch custom integrations now - foreach (CustomIntegration integration in App.Settings.Prop.CustomIntegrations) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})"); - - try - { - Process process = Process.Start(integration.Location, integration.LaunchArgs); - - if (integration.AutoClose) - { - shouldWait = true; - autocloseProcesses.Add(process); - } - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Failed to launch integration '{integration.Name}'! ({ex.Message})"); - } - } - - // event fired, wait for 3 seconds then close - await Task.Delay(3000); - Dialog?.CloseBootstrapper(); - - // keep bloxstrap open in the background if needed - if (!shouldWait) - return; - - activityWatcher?.StartWatcher(); - - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); - - while (Process.GetProcesses().Any(x => x.Id == gameClientPid)) - await Task.Delay(1000); - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Roblox has exited"); - - richPresence?.Dispose(); - - foreach (Process process in autocloseProcesses) - { - if (process.HasExited) - continue; - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); - process.Kill(); - } - } - - public void CancelInstall() - { - if (!_isInstalling) - { - App.Terminate(ERROR_INSTALL_USEREXIT); - return; - } - - App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); - - _cancelTokenSource.Cancel(); - _cancelFired = true; - - try - { - // clean up install - if (App.IsFirstRun) - Directory.Delete(Directories.Base, true); - else if (Directory.Exists(_versionFolder)) - Directory.Delete(_versionFolder, true); - } - catch (Exception ex) - { - App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); - App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {ex}"); - } - - App.Terminate(ERROR_INSTALL_USEREXIT); - } - #endregion - - #region App Install - public static void Register() - { - using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) - { - applicationKey.SetValue("InstallLocation", Directories.Base); - } - - // set uninstall key - using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")) - { - uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); - uninstallKey.SetValue("DisplayName", App.ProjectName); - uninstallKey.SetValue("DisplayVersion", App.Version); - - if (uninstallKey.GetValue("InstallDate") is null) - uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); - - uninstallKey.SetValue("InstallLocation", Directories.Base); - uninstallKey.SetValue("NoRepair", 1); - uninstallKey.SetValue("Publisher", "pizzaboxer"); - uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); - uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); - uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); - uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); - uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); - } - - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); - } - - public void RegisterProgramSize() - { - App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); - - using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); - - // sum compressed and uncompressed package sizes and convert to kilobytes - int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; - - uninstallKey.SetValue("EstimatedSize", totalSize); - - App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); - } - - private void CheckInstallMigration() - { - // check if we've changed our install location since the last time we started - // in which case, we'll have to copy over all our folders so we don't lose any mods and stuff - - using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true); - - string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation"); - - if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base) - return; - - SetStatus("Migrating install location..."); - - if (Directory.Exists(oldInstallLocation)) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}..."); - - foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories)) - { - string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1); - string newFileLocation = Path.Combine(Directories.Base, relativeFile); - string? newDirectory = Path.GetDirectoryName(newFileLocation); - - try - { - if (!String.IsNullOrEmpty(newDirectory)) - Directory.CreateDirectory(newDirectory); - - File.Move(oldFileLocation, newFileLocation, true); - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}"); - } - } - - try - { - Directory.Delete(oldInstallLocation, true); - App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location"); - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}"); - } - } - - applicationKey.DeleteValue("OldInstallLocation"); - - // allow shortcuts to be re-registered - if (Directory.Exists(Directories.StartMenu)) - Directory.Delete(Directories.StartMenu, true); - - if (File.Exists(DesktopShortcutLocation)) - { - File.Delete(DesktopShortcutLocation); - App.Settings.Prop.CreateDesktopIcon = true; - } - - App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!"); - } - - public static void CheckInstall() - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); - - // check if launch uri is set to our bootstrapper - // this doesn't go under register, so we check every launch - // just in case the stock bootstrapper changes it back - - ProtocolHandler.Register("roblox", "Roblox", Directories.Application); - ProtocolHandler.Register("roblox-player", "Roblox", Directories.Application); - - // in case the user is reinstalling - if (File.Exists(Directories.Application) && App.IsFirstRun) - File.Delete(Directories.Application); - - // check to make sure bootstrapper is in the install folder - if (!File.Exists(Directories.Application) && Environment.ProcessPath is not null) - File.Copy(Environment.ProcessPath, Directories.Application); - - // this SHOULD go under Register(), - // but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall - // maybe in a later version? - if (!Directory.Exists(Directories.StartMenu)) - { - Directory.CreateDirectory(Directories.StartMenu); - - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(Path.Combine(Directories.StartMenu, "Play Roblox.lnk")); - - ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) - .WriteToFile(Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk")); - } - else - { - // v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu" - string oldMenuShortcut = Path.Combine(Directories.StartMenu, $"Configure {App.ProjectName}.lnk"); - string newMenuShortcut = Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk"); - - if (File.Exists(oldMenuShortcut)) - File.Delete(oldMenuShortcut); - - if (!File.Exists(newMenuShortcut)) - ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) - .WriteToFile(newMenuShortcut); - } - - if (App.Settings.Prop.CreateDesktopIcon) - { - if (!File.Exists(DesktopShortcutLocation)) - { - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(DesktopShortcutLocation); - } - - // one-time toggle, set it back to false - App.Settings.Prop.CreateDesktopIcon = false; - } - } - - private async Task CheckForUpdates() - { - // don't update if there's another instance running (likely running in the background) - if (Utilities.GetProcessCount(App.ProjectName) > 1) - { - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); - return; - } - - string currentVersion = $"{App.ProjectName} v{App.Version}"; - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); - - var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); - - if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) - { - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); - return; - } - - SetStatus($"Getting the latest {App.ProjectName}..."); - - // 64-bit is always the first option - GithubReleaseAsset asset = releaseInfo.Assets[0]; - string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); - - if (!File.Exists(downloadLocation)) - { - var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl); - - await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); - } - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); - - ProcessStartInfo startInfo = new() - { - FileName = downloadLocation, - }; - - foreach (string arg in App.LaunchArgs) - startInfo.ArgumentList.Add(arg); - - App.Settings.Save(); - - Process.Start(startInfo); - - Environment.Exit(0); - } - - private void Uninstall() - { - // prompt to shutdown roblox if its currently running - if (Utilities.CheckIfRobloxRunning()) - { - App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); - - Dialog?.PromptShutdown(); - - try - { - foreach (Process process in Process.GetProcessesByName("RobloxPlayerBeta")) - { - process.CloseMainWindow(); - process.Close(); - } - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::ShutdownIfRobloxRunning] Failed to close process! {ex}"); - } - - App.Logger.WriteLine($"[Bootstrapper::Uninstall] All Roblox processes closed"); - } - - SetStatus($"Uninstalling {App.ProjectName}..."); - - //App.Settings.ShouldSave = false; - App.ShouldSaveConfigs = false; - - // check if stock bootstrapper is still installed - RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player"); - if (bootstrapperKey is null) - { - ProtocolHandler.Unregister("roblox"); - ProtocolHandler.Unregister("roblox-player"); - } - else - { - // revert launch uri handler to stock bootstrapper - - string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe"; - - ProtocolHandler.Register("roblox", "Roblox", bootstrapperLocation); - ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation); - } - - try - { - // delete application key - Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"); - - // delete start menu folder - Directory.Delete(Directories.StartMenu, true); - - // delete desktop shortcut - File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); - - // delete uninstall key - Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); - - // delete installation folder - // (should delete everything except bloxstrap itself) - Directory.Delete(Directories.Base, true); - } - catch (Exception ex) - { - App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); - } - - Action? callback = null; - - if (Directory.Exists(Directories.Base)) - { - callback = () => - { - // this is definitely one of the workaround hacks of all time - // could antiviruses falsely detect this as malicious behaviour though? - // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" - - Process.Start(new ProcessStartInfo() - { - FileName = "cmd.exe", - Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", - UseShellExecute = true, - WindowStyle = ProcessWindowStyle.Hidden - }); - }; - } - - Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); - } - #endregion - - #region Roblox Install - private async Task InstallLatestVersion() - { - _isInstalling = true; - - SetStatus(FreshInstall ? "Installing Roblox..." : "Upgrading Roblox..."); - - Directory.CreateDirectory(Directories.Base); - Directory.CreateDirectory(Directories.Downloads); - Directory.CreateDirectory(Directories.Versions); - - // package manifest states packed size and uncompressed size in exact bytes - // packed size only matters if we don't already have the package cached on disk - string[] cachedPackages = Directory.GetFiles(Directories.Downloads); - int totalSizeRequired = _versionPackageManifest.Where(x => !cachedPackages.Contains(x.Signature)).Sum(x => x.PackedSize) + _versionPackageManifest.Sum(x => x.Size); - - if (Utilities.GetFreeDiskSpace(Directories.Base) < totalSizeRequired) - { - App.ShowMessageBox($"{App.ProjectName} does not have enough disk space to download and install Roblox. Please free up some disk space and try again.", MessageBoxImage.Error); - App.Terminate(ERROR_INSTALL_FAILURE); - return; - } - - if (Dialog is not null) - { - Dialog.CancelEnabled = true; - Dialog.ProgressStyle = ProgressBarStyle.Continuous; - } - - // compute total bytes to download - _progressIncrement = (double)100 / _versionPackageManifest.Sum(package => package.PackedSize); - - foreach (Package package in _versionPackageManifest) - { - if (_cancelFired) - return; - - // download all the packages synchronously - await DownloadPackage(package); - - // we'll extract the runtime installer later if we need to - if (package.Name == "WebView2RuntimeInstaller.zip") - continue; - - // extract the package immediately after download asynchronously - // discard is just used to suppress the warning - Task _ = ExtractPackage(package); - } - - if (_cancelFired) - return; - - // allow progress bar to 100% before continuing (purely ux reasons lol) - await Task.Delay(1000); - - if (Dialog is not null) - { - Dialog.ProgressStyle = ProgressBarStyle.Marquee; - SetStatus("Configuring Roblox..."); - } - - // wait for all packages to finish extracting, with an exception for the webview2 runtime installer - while (_packagesExtracted < _versionPackageManifest.Where(x => x.Name != "WebView2RuntimeInstaller.zip").Count()) - { - await Task.Delay(100); - } - - string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); - await File.WriteAllTextAsync(appSettingsLocation, AppSettings); - - if (_cancelFired) - return; - - if (!FreshInstall) - { - // let's take this opportunity to delete any packages we don't need anymore - foreach (string filename in cachedPackages) - { - if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) - { - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); - File.Delete(filename); - } - } - - string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); - - // move old compatibility flags for the old location - using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) - { - string oldGameClientLocation = Path.Combine(oldVersionFolder, "RobloxPlayerBeta.exe"); - string? appFlags = (string?)appFlagsKey.GetValue(oldGameClientLocation); - - if (appFlags is not null) - { - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Migrating app compatibility flags from {oldGameClientLocation} to {_playerLocation}..."); - appFlagsKey.SetValue(_playerLocation, appFlags); - appFlagsKey.DeleteValue(oldGameClientLocation); - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows; + +using Microsoft.Win32; + +using Bloxstrap.Enums; +using Bloxstrap.Extensions; +using Bloxstrap.Integrations; +using Bloxstrap.Models; +using Bloxstrap.Tools; +using Bloxstrap.UI.BootstrapperDialogs; + +namespace Bloxstrap +{ + public class Bootstrapper + { + #region Properties + + // https://learn.microsoft.com/en-us/windows/win32/msi/error-codes + public const int ERROR_SUCCESS = 0; + public const int ERROR_INSTALL_USEREXIT = 1602; + public const int ERROR_INSTALL_FAILURE = 1603; + + // in case a new package is added, you can find the corresponding directory + // by opening the stock bootstrapper in a hex editor + // TODO - there ideally should be a less static way to do this that's not hardcoded? + private static readonly IReadOnlyDictionary PackageDirectories = new Dictionary() + { + { "RobloxApp.zip", @"" }, + { "shaders.zip", @"shaders\" }, + { "ssl.zip", @"ssl\" }, + + // the runtime installer is only extracted if it needs installing + { "WebView2.zip", @"" }, + { "WebView2RuntimeInstaller.zip", @"WebView2RuntimeInstaller\" }, + + { "content-avatar.zip", @"content\avatar\" }, + { "content-configs.zip", @"content\configs\" }, + { "content-fonts.zip", @"content\fonts\" }, + { "content-sky.zip", @"content\sky\" }, + { "content-sounds.zip", @"content\sounds\" }, + { "content-textures2.zip", @"content\textures\" }, + { "content-models.zip", @"content\models\" }, + + { "content-textures3.zip", @"PlatformContent\pc\textures\" }, + { "content-terrain.zip", @"PlatformContent\pc\terrain\" }, + { "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" }, + + { "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" }, + { "extracontent-translations.zip", @"ExtraContent\translations\" }, + { "extracontent-models.zip", @"ExtraContent\models\" }, + { "extracontent-textures.zip", @"ExtraContent\textures\" }, + { "extracontent-places.zip", @"ExtraContent\places\" }, + }; + + private const string AppSettings = + "\r\n" + + "\r\n" + + " content\r\n" + + " http://www.roblox.com\r\n" + + "\r\n"; + + private readonly CancellationTokenSource _cancelTokenSource = new(); + + private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); + private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); + + private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); + + private string _launchCommandLine; + + private string _latestVersionGuid = null!; + private PackageManifest _versionPackageManifest = null!; + private string _versionFolder = null!; + + private bool _isInstalling = false; + private double _progressIncrement; + private long _totalDownloadedBytes = 0; + private int _packagesExtracted = 0; + private bool _cancelFired = false; + + public IBootstrapperDialog? Dialog = null; + #endregion + + #region Core + public Bootstrapper(string launchCommandLine) + { + _launchCommandLine = launchCommandLine; + } + + private void SetStatus(string message) + { + App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); + + // yea idk + if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) + message = message.Replace("...", ""); + + if (Dialog is not null) + Dialog.Message = message; + } + + private void UpdateProgressbar() + { + int newProgress = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes); + + // bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100 + // too lazy to fix properly so lol + if (newProgress > 100) + return; + + if (Dialog is not null) + Dialog.ProgressValue = newProgress; + } + + public async Task Run() + { + App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); + + if (App.IsUninstall) + { + Uninstall(); + return; + } + +#if !DEBUG + if (!App.IsFirstRun && App.Settings.Prop.CheckForUpdates) + await CheckForUpdates(); +#endif + + // ensure only one instance of the bootstrapper is running at the time + // so that we don't have stuff like two updates happening simultaneously + + bool mutexExists = false; + + try + { + Mutex.OpenExisting("Bloxstrap_BootstrapperMutex").Close(); + App.Logger.WriteLine("[Bootstrapper::Run] Bloxstrap_BootstrapperMutex mutex exists, waiting..."); + mutexExists = true; + } + catch (Exception) + { + // no mutex exists + } + + // wait for mutex to be released if it's not yet + await using AsyncMutex mutex = new("Bloxstrap_BootstrapperMutex"); + await mutex.AcquireAsync(_cancelTokenSource.Token); + + // reload our configs since they've likely changed by now + if (mutexExists) + { + App.Settings.Load(); + App.State.Load(); + } + + await CheckLatestVersion(); + + CheckInstallMigration(); + + // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist + if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) + await InstallLatestVersion(); + + if (App.IsFirstRun) + App.ShouldSaveConfigs = true; + + MigrateIntegrations(); + + await InstallWebView2(); + + App.FastFlags.Save(); + await ApplyModifications(); + + if (App.IsFirstRun || FreshInstall) + { + Register(); + RegisterProgramSize(); + } + + CheckInstall(); + + // at this point we've finished updating our configs + App.Settings.Save(); + App.State.Save(); + App.ShouldSaveConfigs = false; + + await mutex.ReleaseAsync(); + + if (App.IsFirstRun && App.IsNoLaunch) + Dialog?.ShowSuccess($"{App.ProjectName} has successfully installed"); + else if (!App.IsNoLaunch && !_cancelFired) + await StartRoblox(); + } + + private async Task CheckLatestVersion() + { + SetStatus("Connecting to Roblox..."); + + ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); + + // briefly check if current channel is suitable to use + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) + { + string? switchDefaultPrompt = null; + ClientVersion? defaultChannelInfo = null; + + App.Logger.WriteLine($"[Bootstrapper::CheckLatestVersion] Checking if current channel is suitable to use..."); + + if (String.IsNullOrEmpty(switchDefaultPrompt)) + { + // this SUCKS + defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); + int defaultChannelVersion = Int32.Parse(defaultChannelInfo.Version.Split('.')[1]); + int currentChannelVersion = Int32.Parse(clientVersion.Version.Split('.')[1]); + + if (currentChannelVersion < defaultChannelVersion) + switchDefaultPrompt = $"Your current preferred channel ({App.Settings.Prop.Channel}) appears to no longer be receiving updates. Would you like to switch to {RobloxDeployment.DefaultChannel}?"; + } + + if (!String.IsNullOrEmpty(switchDefaultPrompt)) + { + MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox(switchDefaultPrompt, MessageBoxImage.Question, MessageBoxButton.YesNo); + + if (result == MessageBoxResult.Yes) + { + App.Settings.Prop.Channel = RobloxDeployment.DefaultChannel; + App.Logger.WriteLine($"[DeployManager::SwitchToDefault] Changed Roblox release channel from {App.Settings.Prop.Channel} to {RobloxDeployment.DefaultChannel}"); + + if (defaultChannelInfo is null) + defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); + + clientVersion = defaultChannelInfo; + } + } + } + + _latestVersionGuid = clientVersion.VersionGuid; + _versionFolder = Path.Combine(Directories.Versions, _latestVersionGuid); + _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); + } + + private async Task StartRoblox() + { + SetStatus("Starting Roblox..."); + + if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) + { + Utilities.OpenWebsite("https://www.roblox.com/games"); + Dialog?.CloseBootstrapper(); + return; + } + + _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); + + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) + _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); + + // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes + bool shouldWait = false; + + // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now + int gameClientPid; + using (Process gameClient = Process.Start(_playerLocation, _launchCommandLine)) + { + gameClientPid = gameClient.Id; + } + + List autocloseProcesses = new(); + RobloxActivity? activityWatcher = null; + DiscordRichPresence? richPresence = null; + ServerNotifier? serverNotifier = null; + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Started Roblox (PID {gameClientPid})"); + + using (SystemEvent startEvent = new("www.roblox.com/robloxStartedEvent")) + { + bool startEventFired = await startEvent.WaitForEvent(); + + startEvent.Close(); + + if (!startEventFired) + return; + } + + if (App.Settings.Prop.UseDiscordRichPresence || App.Settings.Prop.ShowServerDetails) + { + activityWatcher = new(); + shouldWait = true; + } + + if (App.Settings.Prop.UseDiscordRichPresence) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); + richPresence = new(activityWatcher!); + } + + if (App.Settings.Prop.ShowServerDetails) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using server details notifier"); + serverNotifier = new(activityWatcher!); + } + + // launch custom integrations now + foreach (CustomIntegration integration in App.Settings.Prop.CustomIntegrations) + { + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})"); + + try + { + Process process = Process.Start(integration.Location, integration.LaunchArgs); + + if (integration.AutoClose) + { + shouldWait = true; + autocloseProcesses.Add(process); + } + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Failed to launch integration '{integration.Name}'! ({ex.Message})"); + } + } + + // event fired, wait for 3 seconds then close + await Task.Delay(3000); + Dialog?.CloseBootstrapper(); + + // keep bloxstrap open in the background if needed + if (!shouldWait) + return; + + activityWatcher?.StartWatcher(); + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); + + while (Process.GetProcesses().Any(x => x.Id == gameClientPid)) + await Task.Delay(1000); + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Roblox has exited"); + + richPresence?.Dispose(); + + foreach (Process process in autocloseProcesses) + { + if (process.HasExited) + continue; + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); + process.Kill(); + } + } + + public void CancelInstall() + { + if (!_isInstalling) + { + App.Terminate(ERROR_INSTALL_USEREXIT); + return; + } + + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); + + _cancelTokenSource.Cancel(); + _cancelFired = true; + + try + { + // clean up install + if (App.IsFirstRun) + Directory.Delete(Directories.Base, true); + else if (Directory.Exists(_versionFolder)) + Directory.Delete(_versionFolder, true); + } + catch (Exception ex) + { + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); + App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {ex}"); + } + + App.Terminate(ERROR_INSTALL_USEREXIT); + } + #endregion + + #region App Install + public static void Register() + { + using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) + { + applicationKey.SetValue("InstallLocation", Directories.Base); + } + + // set uninstall key + using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")) + { + uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); + uninstallKey.SetValue("DisplayName", App.ProjectName); + uninstallKey.SetValue("DisplayVersion", App.Version); + + if (uninstallKey.GetValue("InstallDate") is null) + uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); + + uninstallKey.SetValue("InstallLocation", Directories.Base); + uninstallKey.SetValue("NoRepair", 1); + uninstallKey.SetValue("Publisher", "pizzaboxer"); + uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); + uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); + uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); + uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); + uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); + } + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); + } + + public void RegisterProgramSize() + { + App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); + + using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); + + // sum compressed and uncompressed package sizes and convert to kilobytes + int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; + + uninstallKey.SetValue("EstimatedSize", totalSize); + + App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); + } + + private void CheckInstallMigration() + { + // check if we've changed our install location since the last time we started + // in which case, we'll have to copy over all our folders so we don't lose any mods and stuff + + using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true); + + string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation"); + + if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base) + return; + + SetStatus("Migrating install location..."); + + if (Directory.Exists(oldInstallLocation)) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}..."); + + foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories)) + { + string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1); + string newFileLocation = Path.Combine(Directories.Base, relativeFile); + string? newDirectory = Path.GetDirectoryName(newFileLocation); + + try + { + if (!String.IsNullOrEmpty(newDirectory)) + Directory.CreateDirectory(newDirectory); + + File.Move(oldFileLocation, newFileLocation, true); + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}"); + } + } + + try + { + Directory.Delete(oldInstallLocation, true); + App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location"); + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}"); + } + } + + applicationKey.DeleteValue("OldInstallLocation"); + + // allow shortcuts to be re-registered + if (Directory.Exists(Directories.StartMenu)) + Directory.Delete(Directories.StartMenu, true); + + if (File.Exists(DesktopShortcutLocation)) + { + File.Delete(DesktopShortcutLocation); + App.Settings.Prop.CreateDesktopIcon = true; + } + + App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!"); + } + + public static void CheckInstall() + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); + + // check if launch uri is set to our bootstrapper + // this doesn't go under register, so we check every launch + // just in case the stock bootstrapper changes it back + + ProtocolHandler.Register("roblox", "Roblox", Directories.Application); + ProtocolHandler.Register("roblox-player", "Roblox", Directories.Application); + + // in case the user is reinstalling + if (File.Exists(Directories.Application) && App.IsFirstRun) + File.Delete(Directories.Application); + + // check to make sure bootstrapper is in the install folder + if (!File.Exists(Directories.Application) && Environment.ProcessPath is not null) + File.Copy(Environment.ProcessPath, Directories.Application); + + // this SHOULD go under Register(), + // but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall + // maybe in a later version? + if (!Directory.Exists(Directories.StartMenu)) + { + Directory.CreateDirectory(Directories.StartMenu); + + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(Path.Combine(Directories.StartMenu, "Play Roblox.lnk")); + + ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) + .WriteToFile(Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk")); + } + else + { + // v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu" + string oldMenuShortcut = Path.Combine(Directories.StartMenu, $"Configure {App.ProjectName}.lnk"); + string newMenuShortcut = Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk"); + + if (File.Exists(oldMenuShortcut)) + File.Delete(oldMenuShortcut); + + if (!File.Exists(newMenuShortcut)) + ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) + .WriteToFile(newMenuShortcut); + } + + if (App.Settings.Prop.CreateDesktopIcon) + { + if (!File.Exists(DesktopShortcutLocation)) + { + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(DesktopShortcutLocation); + } + + // one-time toggle, set it back to false + App.Settings.Prop.CreateDesktopIcon = false; + } + } + + private async Task CheckForUpdates() + { + // don't update if there's another instance running (likely running in the background) + if (Utilities.GetProcessCount(App.ProjectName) > 1) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); + return; + } + + string currentVersion = $"{App.ProjectName} v{App.Version}"; + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); + + var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); + + if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); + return; + } + + SetStatus($"Getting the latest {App.ProjectName}..."); + + // 64-bit is always the first option + GithubReleaseAsset asset = releaseInfo.Assets[0]; + string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); + + if (!File.Exists(downloadLocation)) + { + var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl); + + await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + } + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); + + ProcessStartInfo startInfo = new() + { + FileName = downloadLocation, + }; + + foreach (string arg in App.LaunchArgs) + startInfo.ArgumentList.Add(arg); + + App.Settings.Save(); + + Process.Start(startInfo); + + Environment.Exit(0); + } + + private void Uninstall() + { + // prompt to shutdown roblox if its currently running + if (Utilities.CheckIfRobloxRunning()) + { + App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); + + Dialog?.PromptShutdown(); + + try + { + foreach (Process process in Process.GetProcessesByName("RobloxPlayerBeta")) + { + process.CloseMainWindow(); + process.Close(); + } + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::ShutdownIfRobloxRunning] Failed to close process! {ex}"); + } + + App.Logger.WriteLine($"[Bootstrapper::Uninstall] All Roblox processes closed"); + } + + SetStatus($"Uninstalling {App.ProjectName}..."); + + //App.Settings.ShouldSave = false; + App.ShouldSaveConfigs = false; + + // check if stock bootstrapper is still installed + RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player"); + if (bootstrapperKey is null) + { + ProtocolHandler.Unregister("roblox"); + ProtocolHandler.Unregister("roblox-player"); + } + else + { + // revert launch uri handler to stock bootstrapper + + string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe"; + + ProtocolHandler.Register("roblox", "Roblox", bootstrapperLocation); + ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation); + } + + try + { + // delete application key + Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"); + + // delete start menu folder + Directory.Delete(Directories.StartMenu, true); + + // delete desktop shortcut + File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); + + // delete uninstall key + Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); + + // delete installation folder + // (should delete everything except bloxstrap itself) + Directory.Delete(Directories.Base, true); + } + catch (Exception ex) + { + App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); + } + + Action? callback = null; + + if (Directory.Exists(Directories.Base)) + { + callback = () => + { + // this is definitely one of the workaround hacks of all time + // could antiviruses falsely detect this as malicious behaviour though? + // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" + + Process.Start(new ProcessStartInfo() + { + FileName = "cmd.exe", + Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", + UseShellExecute = true, + WindowStyle = ProcessWindowStyle.Hidden + }); + }; + } + + Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); + } + #endregion + + #region Roblox Install + private async Task InstallLatestVersion() + { + _isInstalling = true; + + SetStatus(FreshInstall ? "Installing Roblox..." : "Upgrading Roblox..."); + + Directory.CreateDirectory(Directories.Base); + Directory.CreateDirectory(Directories.Downloads); + Directory.CreateDirectory(Directories.Versions); + + // package manifest states packed size and uncompressed size in exact bytes + // packed size only matters if we don't already have the package cached on disk + string[] cachedPackages = Directory.GetFiles(Directories.Downloads); + int totalSizeRequired = _versionPackageManifest.Where(x => !cachedPackages.Contains(x.Signature)).Sum(x => x.PackedSize) + _versionPackageManifest.Sum(x => x.Size); + + if (Utilities.GetFreeDiskSpace(Directories.Base) < totalSizeRequired) + { + App.ShowMessageBox($"{App.ProjectName} does not have enough disk space to download and install Roblox. Please free up some disk space and try again.", MessageBoxImage.Error); + App.Terminate(ERROR_INSTALL_FAILURE); + return; + } + + if (Dialog is not null) + { + Dialog.CancelEnabled = true; + Dialog.ProgressStyle = ProgressBarStyle.Continuous; + } + + // compute total bytes to download + _progressIncrement = (double)100 / _versionPackageManifest.Sum(package => package.PackedSize); + + foreach (Package package in _versionPackageManifest) + { + if (_cancelFired) + return; + + // download all the packages synchronously + await DownloadPackage(package); + + // we'll extract the runtime installer later if we need to + if (package.Name == "WebView2RuntimeInstaller.zip") + continue; + + // extract the package immediately after download asynchronously + // discard is just used to suppress the warning + Task _ = ExtractPackage(package); + } + + if (_cancelFired) + return; + + // allow progress bar to 100% before continuing (purely ux reasons lol) + await Task.Delay(1000); + + if (Dialog is not null) + { + Dialog.ProgressStyle = ProgressBarStyle.Marquee; + SetStatus("Configuring Roblox..."); + } + + // wait for all packages to finish extracting, with an exception for the webview2 runtime installer + while (_packagesExtracted < _versionPackageManifest.Where(x => x.Name != "WebView2RuntimeInstaller.zip").Count()) + { + await Task.Delay(100); + } + + string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); + await File.WriteAllTextAsync(appSettingsLocation, AppSettings); + + if (_cancelFired) + return; + + if (!FreshInstall) + { + // let's take this opportunity to delete any packages we don't need anymore + foreach (string filename in cachedPackages) + { + if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) + { + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); + File.Delete(filename); + } + } + + string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); + + // move old compatibility flags for the old location + using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) + { + string oldGameClientLocation = Path.Combine(oldVersionFolder, "RobloxPlayerBeta.exe"); + string? appFlags = (string?)appFlagsKey.GetValue(oldGameClientLocation); + + if (appFlags is not null) + { + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Migrating app compatibility flags from {oldGameClientLocation} to {_playerLocation}..."); + appFlagsKey.SetValue(_playerLocation, appFlags); + appFlagsKey.DeleteValue(oldGameClientLocation); + } } // delete any old version folders // we only do this if roblox isnt running just in case an update happened // while they were launching a second instance or something idk - if (!Process.GetProcessesByName(App.RobloxAppName).Any()) - { - foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) - { - if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) - continue; - - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); - dir.Delete(true); - } - } - } - - App.State.Prop.VersionGuid = _latestVersionGuid; - - // don't register program size until the program is registered, which will be done after this - if (!App.IsFirstRun && !FreshInstall) - RegisterProgramSize(); - - if (Dialog is not null) - Dialog.CancelEnabled = false; - - _isInstalling = false; - } - - private async Task InstallWebView2() - { - // check if the webview2 runtime needs to be installed - // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu - // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed - - using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - using RegistryKey? hkcuKey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - - if (hklmKey is not null || hkcuKey is not null) - return; - - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); - - string baseDirectory = Path.Combine(_versionFolder, "WebView2RuntimeInstaller"); - - if (!Directory.Exists(baseDirectory)) - { - Package? package = _versionPackageManifest.Find(x => x.Name == "WebView2RuntimeInstaller.zip"); - - if (package is null) - { - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Aborted runtime install because package does not exist, has WebView2 been added in this Roblox version yet?"); - return; - } - - await ExtractPackage(package); - } - - SetStatus("Installing WebView2, please wait..."); - - ProcessStartInfo startInfo = new() - { - WorkingDirectory = baseDirectory, - FileName = Path.Combine(baseDirectory, "MicrosoftEdgeWebview2Setup.exe"), - Arguments = "/silent /install" - }; - - await Process.Start(startInfo)!.WaitForExitAsync(); - - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Finished installing runtime"); - } - - public static void MigrateIntegrations() - { - // v2.2.0 - remove rbxfpsunlocker - string rbxfpsunlocker = Path.Combine(Directories.Integrations, "rbxfpsunlocker"); - - if (Directory.Exists(rbxfpsunlocker)) - Directory.Delete(rbxfpsunlocker, true); - - // v2.3.0 - remove reshade - string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); - string configLocation = Path.Combine(Directories.Modifications, "ReShade.ini"); - - if (File.Exists(injectorLocation)) - { - App.ShowMessageBox( - "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ - "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", - MessageBoxImage.Warning - ); - - File.Delete(injectorLocation); - } - - if (File.Exists(configLocation)) - File.Delete(configLocation); - } - - private async Task ApplyModifications() - { - SetStatus("Applying Roblox modifications..."); - - // set executable flags for fullscreen optimizations - App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking executable flags..."); - using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) - { - const string flag = " DISABLEDXMAXIMIZEDWINDOWEDMODE"; - string? appFlags = (string?)appFlagsKey.GetValue(_playerLocation); - - if (App.Settings.Prop.DisableFullscreenOptimizations) - { - if (appFlags is null) - appFlagsKey.SetValue(_playerLocation, $"~{flag}"); - else if (!appFlags.Contains(flag)) - appFlagsKey.SetValue(_playerLocation, appFlags + flag); - } - else if (appFlags is not null && appFlags.Contains(flag)) - { - // if there's more than one space, there's more flags set we need to preserve - if (appFlags.Split(' ').Length > 2) - appFlagsKey.SetValue(_playerLocation, appFlags.Remove(appFlags.IndexOf(flag), flag.Length)); - else - appFlagsKey.DeleteValue(_playerLocation); - } - } - - // handle file mods - App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking file mods..."); - string modFolder = Path.Combine(Directories.Modifications); - - // manifest has been moved to State.json - File.Delete(Path.Combine(Directories.Base, "ModManifest.txt")); - - List modFolderFiles = new(); - - if (!Directory.Exists(modFolder)) - Directory.CreateDirectory(modFolder); - - await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseDisableAppPatch, @"ExtraContent\places\Mobile.rbxl", ""); - - // emoji presets are downloaded remotely from github due to how large they are - string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); - - if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) - { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - App.State.Prop.CurrentEmojiType = EmojiType.Default; - } - else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) - { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); - - var response = await App.HttpClient.GetAsync(remoteEmojiLocation); - await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); - - App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; - } - - foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) - { - // get relative directory path - string relativeFile = file.Substring(modFolder.Length + 1); - - // v1.7.0 - README has been moved to the preferences menu now - if (relativeFile == "README.txt") - { - File.Delete(file); - continue; - } - - modFolderFiles.Add(relativeFile); - } - - // copy and overwrite - foreach (string file in modFolderFiles) - { - string fileModFolder = Path.Combine(modFolder, file); - string fileVersionFolder = Path.Combine(_versionFolder, file); - - if (File.Exists(fileVersionFolder)) - { - if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) - continue; - } - - string? directory = Path.GetDirectoryName(fileVersionFolder); - - if (directory is null) - continue; - - Directory.CreateDirectory(directory); - - File.Copy(fileModFolder, fileVersionFolder, true); - File.SetAttributes(fileVersionFolder, File.GetAttributes(fileModFolder) & ~FileAttributes.ReadOnly); - } - - // the manifest is primarily here to keep track of what files have been - // deleted from the modifications folder, so that we know when to restore the original files from the downloaded packages - // now check for files that have been deleted from the mod folder according to the manifest - foreach (string fileLocation in App.State.Prop.ModManifest) - { - if (modFolderFiles.Contains(fileLocation)) - continue; - - KeyValuePair packageDirectory; - - try - { - packageDirectory = PackageDirectories.First(x => x.Value != "" && fileLocation.StartsWith(x.Value)); - } - catch (InvalidOperationException) - { - // package doesn't exist, likely mistakenly placed file - string versionFileLocation = Path.Combine(_versionFolder, fileLocation); - - if (File.Exists(versionFileLocation)) - File.Delete(versionFileLocation); - - continue; - } - - // restore original file - string fileName = fileLocation.Substring(packageDirectory.Value.Length); - ExtractFileFromPackage(packageDirectory.Key, fileName); - } - - App.State.Prop.ModManifest = modFolderFiles; - App.State.Save(); - } - - private static async Task CheckModPreset(bool condition, string location, string name) - { - string modFolderLocation = Path.Combine(Directories.Modifications, location); - byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); - - if (condition) - { - if (!File.Exists(modFolderLocation)) - { - string? directory = Path.GetDirectoryName(modFolderLocation); - - if (directory is null) - return; - - Directory.CreateDirectory(directory); - - await File.WriteAllBytesAsync(modFolderLocation, binaryData); - } - } - else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) - { - File.Delete(modFolderLocation); - } - } - - private async Task DownloadPackage(Package package) - { - if (_cancelFired) - return; - - string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}"); - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string robloxPackageLocation = Path.Combine(Directories.LocalAppData, "Roblox", "Downloads", package.Signature); - - if (File.Exists(packageLocation)) - { - FileInfo file = new(packageLocation); - - string calculatedMD5 = Utilities.MD5File(packageLocation); - if (calculatedMD5 != package.Signature) - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); - file.Delete(); - } - else - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); - _totalDownloadedBytes += package.PackedSize; - UpdateProgressbar(); - return; - } - } - else if (File.Exists(robloxPackageLocation)) - { - // let's cheat! if the stock bootstrapper already previously downloaded the file, - // then we can just copy the one from there - - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); - File.Copy(robloxPackageLocation, packageLocation); - _totalDownloadedBytes += package.PackedSize; - UpdateProgressbar(); - return; - } - - if (!File.Exists(packageLocation)) - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); - - { - var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); - var buffer = new byte[4096]; - - await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token); - await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete); - - while (true) - { - if (_cancelFired) - { - stream.Close(); - fileStream.Close(); - return; - } - - var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cancelTokenSource.Token); - - if (bytesRead == 0) - break; // we're done - - await fileStream.WriteAsync(buffer, 0, bytesRead, _cancelTokenSource.Token); - - _totalDownloadedBytes += bytesRead; - UpdateProgressbar(); - } - } - - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); - } - } - - private async Task ExtractPackage(Package package) - { - if (_cancelFired) - return; - - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); - string extractPath; - - App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); - - using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) - { - foreach (ZipArchiveEntry entry in archive.Entries) - { - if (_cancelFired) - return; - - if (entry.FullName.EndsWith('\\')) - continue; - - extractPath = Path.Combine(packageFolder, entry.FullName); - - //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); - - string? directory = Path.GetDirectoryName(extractPath); - - if (directory is null) - continue; - - Directory.CreateDirectory(directory); - - await Task.Run(() => entry.ExtractToFile(extractPath, true)); - } - } - - App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); - - _packagesExtracted += 1; - } - - private void ExtractFileFromPackage(string packageName, string fileName) - { - Package? package = _versionPackageManifest.Find(x => x.Name == packageName); - - if (package is null) - return; - - DownloadPackage(package).GetAwaiter().GetResult(); - - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); - - using ZipArchive archive = ZipFile.OpenRead(packageLocation); - - ZipArchiveEntry? entry = archive.Entries.FirstOrDefault(x => x.FullName == fileName); - - if (entry is null) - return; - - string fileLocation = Path.Combine(packageFolder, entry.FullName); - - File.Delete(fileLocation); - - entry.ExtractToFile(fileLocation); - } - #endregion - } -} + if (!Process.GetProcessesByName(App.RobloxAppName).Any()) + { + foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) + { + if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) + continue; + + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); + dir.Delete(true); + } + } + } + + App.State.Prop.VersionGuid = _latestVersionGuid; + + // don't register program size until the program is registered, which will be done after this + if (!App.IsFirstRun && !FreshInstall) + RegisterProgramSize(); + + if (Dialog is not null) + Dialog.CancelEnabled = false; + + _isInstalling = false; + } + + private async Task InstallWebView2() + { + // check if the webview2 runtime needs to be installed + // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu + // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed + + using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + using RegistryKey? hkcuKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + + if (hklmKey is not null || hkcuKey is not null) + return; + + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); + + string baseDirectory = Path.Combine(_versionFolder, "WebView2RuntimeInstaller"); + + if (!Directory.Exists(baseDirectory)) + { + Package? package = _versionPackageManifest.Find(x => x.Name == "WebView2RuntimeInstaller.zip"); + + if (package is null) + { + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Aborted runtime install because package does not exist, has WebView2 been added in this Roblox version yet?"); + return; + } + + await ExtractPackage(package); + } + + SetStatus("Installing WebView2, please wait..."); + + ProcessStartInfo startInfo = new() + { + WorkingDirectory = baseDirectory, + FileName = Path.Combine(baseDirectory, "MicrosoftEdgeWebview2Setup.exe"), + Arguments = "/silent /install" + }; + + await Process.Start(startInfo)!.WaitForExitAsync(); + + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Finished installing runtime"); + } + + public static void MigrateIntegrations() + { + // v2.2.0 - remove rbxfpsunlocker + string rbxfpsunlocker = Path.Combine(Directories.Integrations, "rbxfpsunlocker"); + + if (Directory.Exists(rbxfpsunlocker)) + Directory.Delete(rbxfpsunlocker, true); + + // v2.3.0 - remove reshade + string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); + string configLocation = Path.Combine(Directories.Modifications, "ReShade.ini"); + + if (File.Exists(injectorLocation)) + { + App.ShowMessageBox( + "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ + "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", + MessageBoxImage.Warning + ); + + File.Delete(injectorLocation); + } + + if (File.Exists(configLocation)) + File.Delete(configLocation); + } + + private async Task ApplyModifications() + { + SetStatus("Applying Roblox modifications..."); + + // set executable flags for fullscreen optimizations + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking executable flags..."); + using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) + { + const string flag = " DISABLEDXMAXIMIZEDWINDOWEDMODE"; + string? appFlags = (string?)appFlagsKey.GetValue(_playerLocation); + + if (App.Settings.Prop.DisableFullscreenOptimizations) + { + if (appFlags is null) + appFlagsKey.SetValue(_playerLocation, $"~{flag}"); + else if (!appFlags.Contains(flag)) + appFlagsKey.SetValue(_playerLocation, appFlags + flag); + } + else if (appFlags is not null && appFlags.Contains(flag)) + { + // if there's more than one space, there's more flags set we need to preserve + if (appFlags.Split(' ').Length > 2) + appFlagsKey.SetValue(_playerLocation, appFlags.Remove(appFlags.IndexOf(flag), flag.Length)); + else + appFlagsKey.DeleteValue(_playerLocation); + } + } + + // handle file mods + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking file mods..."); + string modFolder = Path.Combine(Directories.Modifications); + + // manifest has been moved to State.json + File.Delete(Path.Combine(Directories.Base, "ModManifest.txt")); + + List modFolderFiles = new(); + + if (!Directory.Exists(modFolder)) + Directory.CreateDirectory(modFolder); + + await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); + await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); + await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseDisableAppPatch, @"ExtraContent\places\Mobile.rbxl", ""); + + // emoji presets are downloaded remotely from github due to how large they are + string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); + + if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + App.State.Prop.CurrentEmojiType = EmojiType.Default; + } + else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); + + var response = await App.HttpClient.GetAsync(remoteEmojiLocation); + await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + + App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; + } + + foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) + { + // get relative directory path + string relativeFile = file.Substring(modFolder.Length + 1); + + // v1.7.0 - README has been moved to the preferences menu now + if (relativeFile == "README.txt") + { + File.Delete(file); + continue; + } + + modFolderFiles.Add(relativeFile); + } + + // copy and overwrite + foreach (string file in modFolderFiles) + { + string fileModFolder = Path.Combine(modFolder, file); + string fileVersionFolder = Path.Combine(_versionFolder, file); + + if (File.Exists(fileVersionFolder)) + { + if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) + continue; + } + + string? directory = Path.GetDirectoryName(fileVersionFolder); + + if (directory is null) + continue; + + Directory.CreateDirectory(directory); + + File.Copy(fileModFolder, fileVersionFolder, true); + File.SetAttributes(fileVersionFolder, File.GetAttributes(fileModFolder) & ~FileAttributes.ReadOnly); + } + + // the manifest is primarily here to keep track of what files have been + // deleted from the modifications folder, so that we know when to restore the original files from the downloaded packages + // now check for files that have been deleted from the mod folder according to the manifest + foreach (string fileLocation in App.State.Prop.ModManifest) + { + if (modFolderFiles.Contains(fileLocation)) + continue; + + KeyValuePair packageDirectory; + + try + { + packageDirectory = PackageDirectories.First(x => x.Value != "" && fileLocation.StartsWith(x.Value)); + } + catch (InvalidOperationException) + { + // package doesn't exist, likely mistakenly placed file + string versionFileLocation = Path.Combine(_versionFolder, fileLocation); + + if (File.Exists(versionFileLocation)) + File.Delete(versionFileLocation); + + continue; + } + + // restore original file + string fileName = fileLocation.Substring(packageDirectory.Value.Length); + ExtractFileFromPackage(packageDirectory.Key, fileName); + } + + App.State.Prop.ModManifest = modFolderFiles; + App.State.Save(); + } + + private static async Task CheckModPreset(bool condition, string location, string name) + { + string modFolderLocation = Path.Combine(Directories.Modifications, location); + byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); + + if (condition) + { + if (!File.Exists(modFolderLocation)) + { + string? directory = Path.GetDirectoryName(modFolderLocation); + + if (directory is null) + return; + + Directory.CreateDirectory(directory); + + await File.WriteAllBytesAsync(modFolderLocation, binaryData); + } + } + else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) + { + File.Delete(modFolderLocation); + } + } + + private async Task DownloadPackage(Package package) + { + if (_cancelFired) + return; + + string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}"); + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string robloxPackageLocation = Path.Combine(Directories.LocalAppData, "Roblox", "Downloads", package.Signature); + + if (File.Exists(packageLocation)) + { + FileInfo file = new(packageLocation); + + string calculatedMD5 = Utilities.MD5File(packageLocation); + if (calculatedMD5 != package.Signature) + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); + file.Delete(); + } + else + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); + _totalDownloadedBytes += package.PackedSize; + UpdateProgressbar(); + return; + } + } + else if (File.Exists(robloxPackageLocation)) + { + // let's cheat! if the stock bootstrapper already previously downloaded the file, + // then we can just copy the one from there + + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); + File.Copy(robloxPackageLocation, packageLocation); + _totalDownloadedBytes += package.PackedSize; + UpdateProgressbar(); + return; + } + + if (!File.Exists(packageLocation)) + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); + + { + var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); + var buffer = new byte[4096]; + + await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token); + await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete); + + while (true) + { + if (_cancelFired) + { + stream.Close(); + fileStream.Close(); + return; + } + + var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cancelTokenSource.Token); + + if (bytesRead == 0) + break; // we're done + + await fileStream.WriteAsync(buffer, 0, bytesRead, _cancelTokenSource.Token); + + _totalDownloadedBytes += bytesRead; + UpdateProgressbar(); + } + } + + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); + } + } + + private async Task ExtractPackage(Package package) + { + if (_cancelFired) + return; + + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); + string extractPath; + + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); + + using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) + { + foreach (ZipArchiveEntry entry in archive.Entries) + { + if (_cancelFired) + return; + + if (entry.FullName.EndsWith('\\')) + continue; + + extractPath = Path.Combine(packageFolder, entry.FullName); + + //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); + + string? directory = Path.GetDirectoryName(extractPath); + + if (directory is null) + continue; + + Directory.CreateDirectory(directory); + + await Task.Run(() => entry.ExtractToFile(extractPath, true)); + } + } + + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); + + _packagesExtracted += 1; + } + + private void ExtractFileFromPackage(string packageName, string fileName) + { + Package? package = _versionPackageManifest.Find(x => x.Name == packageName); + + if (package is null) + return; + + DownloadPackage(package).GetAwaiter().GetResult(); + + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); + + using ZipArchive archive = ZipFile.OpenRead(packageLocation); + + ZipArchiveEntry? entry = archive.Entries.FirstOrDefault(x => x.FullName == fileName); + + if (entry is null) + return; + + string fileLocation = Path.Combine(packageFolder, entry.FullName); + + File.Delete(fileLocation); + + entry.ExtractToFile(fileLocation); + } + #endregion + } +} From 59bda907d33ff1319a34e8a46d9d881e0f299219 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 13 Jun 2023 08:13:40 +0100 Subject: [PATCH 055/178] Revert "WebView2 bugfix" This reverts commit a71f8e5606f3f2c19adf96e3ea3c6ca74446d5b8. it was not supposed to do that :( whyyyyyyyyy --- Bloxstrap/Bootstrapper.cs | 2438 ++++++++++++++++++------------------- 1 file changed, 1219 insertions(+), 1219 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 7c5059b5..7cf2a02d 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1,1224 +1,1224 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using System.Windows; - -using Microsoft.Win32; - -using Bloxstrap.Enums; -using Bloxstrap.Extensions; -using Bloxstrap.Integrations; -using Bloxstrap.Models; -using Bloxstrap.Tools; -using Bloxstrap.UI.BootstrapperDialogs; - -namespace Bloxstrap -{ - public class Bootstrapper - { - #region Properties - - // https://learn.microsoft.com/en-us/windows/win32/msi/error-codes - public const int ERROR_SUCCESS = 0; - public const int ERROR_INSTALL_USEREXIT = 1602; - public const int ERROR_INSTALL_FAILURE = 1603; - - // in case a new package is added, you can find the corresponding directory - // by opening the stock bootstrapper in a hex editor - // TODO - there ideally should be a less static way to do this that's not hardcoded? - private static readonly IReadOnlyDictionary PackageDirectories = new Dictionary() - { - { "RobloxApp.zip", @"" }, - { "shaders.zip", @"shaders\" }, - { "ssl.zip", @"ssl\" }, - - // the runtime installer is only extracted if it needs installing - { "WebView2.zip", @"" }, - { "WebView2RuntimeInstaller.zip", @"WebView2RuntimeInstaller\" }, - - { "content-avatar.zip", @"content\avatar\" }, - { "content-configs.zip", @"content\configs\" }, - { "content-fonts.zip", @"content\fonts\" }, - { "content-sky.zip", @"content\sky\" }, - { "content-sounds.zip", @"content\sounds\" }, - { "content-textures2.zip", @"content\textures\" }, - { "content-models.zip", @"content\models\" }, - - { "content-textures3.zip", @"PlatformContent\pc\textures\" }, - { "content-terrain.zip", @"PlatformContent\pc\terrain\" }, - { "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" }, - - { "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" }, - { "extracontent-translations.zip", @"ExtraContent\translations\" }, - { "extracontent-models.zip", @"ExtraContent\models\" }, - { "extracontent-textures.zip", @"ExtraContent\textures\" }, - { "extracontent-places.zip", @"ExtraContent\places\" }, - }; - - private const string AppSettings = - "\r\n" + - "\r\n" + - " content\r\n" + - " http://www.roblox.com\r\n" + - "\r\n"; - - private readonly CancellationTokenSource _cancelTokenSource = new(); - - private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); - private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); - - private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); - - private string _launchCommandLine; - - private string _latestVersionGuid = null!; - private PackageManifest _versionPackageManifest = null!; - private string _versionFolder = null!; - - private bool _isInstalling = false; - private double _progressIncrement; - private long _totalDownloadedBytes = 0; - private int _packagesExtracted = 0; - private bool _cancelFired = false; - - public IBootstrapperDialog? Dialog = null; - #endregion - - #region Core - public Bootstrapper(string launchCommandLine) - { - _launchCommandLine = launchCommandLine; - } - - private void SetStatus(string message) - { - App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); - - // yea idk - if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) - message = message.Replace("...", ""); - - if (Dialog is not null) - Dialog.Message = message; - } - - private void UpdateProgressbar() - { - int newProgress = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes); - - // bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100 - // too lazy to fix properly so lol - if (newProgress > 100) - return; - - if (Dialog is not null) - Dialog.ProgressValue = newProgress; - } - - public async Task Run() - { - App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); - - if (App.IsUninstall) - { - Uninstall(); - return; - } - -#if !DEBUG - if (!App.IsFirstRun && App.Settings.Prop.CheckForUpdates) - await CheckForUpdates(); -#endif - - // ensure only one instance of the bootstrapper is running at the time - // so that we don't have stuff like two updates happening simultaneously - - bool mutexExists = false; - - try - { - Mutex.OpenExisting("Bloxstrap_BootstrapperMutex").Close(); - App.Logger.WriteLine("[Bootstrapper::Run] Bloxstrap_BootstrapperMutex mutex exists, waiting..."); - mutexExists = true; - } - catch (Exception) - { - // no mutex exists - } - - // wait for mutex to be released if it's not yet - await using AsyncMutex mutex = new("Bloxstrap_BootstrapperMutex"); - await mutex.AcquireAsync(_cancelTokenSource.Token); - - // reload our configs since they've likely changed by now - if (mutexExists) - { - App.Settings.Load(); - App.State.Load(); - } - - await CheckLatestVersion(); - - CheckInstallMigration(); - - // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist - if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) - await InstallLatestVersion(); - - if (App.IsFirstRun) - App.ShouldSaveConfigs = true; - - MigrateIntegrations(); - - await InstallWebView2(); - - App.FastFlags.Save(); - await ApplyModifications(); - - if (App.IsFirstRun || FreshInstall) - { - Register(); - RegisterProgramSize(); - } - - CheckInstall(); - - // at this point we've finished updating our configs - App.Settings.Save(); - App.State.Save(); - App.ShouldSaveConfigs = false; - - await mutex.ReleaseAsync(); - - if (App.IsFirstRun && App.IsNoLaunch) - Dialog?.ShowSuccess($"{App.ProjectName} has successfully installed"); - else if (!App.IsNoLaunch && !_cancelFired) - await StartRoblox(); - } - - private async Task CheckLatestVersion() - { - SetStatus("Connecting to Roblox..."); - - ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); - - // briefly check if current channel is suitable to use - if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) - { - string? switchDefaultPrompt = null; - ClientVersion? defaultChannelInfo = null; - - App.Logger.WriteLine($"[Bootstrapper::CheckLatestVersion] Checking if current channel is suitable to use..."); - - if (String.IsNullOrEmpty(switchDefaultPrompt)) - { - // this SUCKS - defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); - int defaultChannelVersion = Int32.Parse(defaultChannelInfo.Version.Split('.')[1]); - int currentChannelVersion = Int32.Parse(clientVersion.Version.Split('.')[1]); - - if (currentChannelVersion < defaultChannelVersion) - switchDefaultPrompt = $"Your current preferred channel ({App.Settings.Prop.Channel}) appears to no longer be receiving updates. Would you like to switch to {RobloxDeployment.DefaultChannel}?"; - } - - if (!String.IsNullOrEmpty(switchDefaultPrompt)) - { - MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox(switchDefaultPrompt, MessageBoxImage.Question, MessageBoxButton.YesNo); - - if (result == MessageBoxResult.Yes) - { - App.Settings.Prop.Channel = RobloxDeployment.DefaultChannel; - App.Logger.WriteLine($"[DeployManager::SwitchToDefault] Changed Roblox release channel from {App.Settings.Prop.Channel} to {RobloxDeployment.DefaultChannel}"); - - if (defaultChannelInfo is null) - defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); - - clientVersion = defaultChannelInfo; - } - } - } - - _latestVersionGuid = clientVersion.VersionGuid; - _versionFolder = Path.Combine(Directories.Versions, _latestVersionGuid); - _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); - } - - private async Task StartRoblox() - { - SetStatus("Starting Roblox..."); - - if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) - { - Utilities.OpenWebsite("https://www.roblox.com/games"); - Dialog?.CloseBootstrapper(); - return; - } - - _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); - - if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) - _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); - - // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes - bool shouldWait = false; - - // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now - int gameClientPid; - using (Process gameClient = Process.Start(_playerLocation, _launchCommandLine)) - { - gameClientPid = gameClient.Id; - } - - List autocloseProcesses = new(); - RobloxActivity? activityWatcher = null; - DiscordRichPresence? richPresence = null; - ServerNotifier? serverNotifier = null; - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Started Roblox (PID {gameClientPid})"); - - using (SystemEvent startEvent = new("www.roblox.com/robloxStartedEvent")) - { - bool startEventFired = await startEvent.WaitForEvent(); - - startEvent.Close(); - - if (!startEventFired) - return; - } - - if (App.Settings.Prop.UseDiscordRichPresence || App.Settings.Prop.ShowServerDetails) - { - activityWatcher = new(); - shouldWait = true; - } - - if (App.Settings.Prop.UseDiscordRichPresence) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); - richPresence = new(activityWatcher!); - } - - if (App.Settings.Prop.ShowServerDetails) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using server details notifier"); - serverNotifier = new(activityWatcher!); - } - - // launch custom integrations now - foreach (CustomIntegration integration in App.Settings.Prop.CustomIntegrations) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})"); - - try - { - Process process = Process.Start(integration.Location, integration.LaunchArgs); - - if (integration.AutoClose) - { - shouldWait = true; - autocloseProcesses.Add(process); - } - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Failed to launch integration '{integration.Name}'! ({ex.Message})"); - } - } - - // event fired, wait for 3 seconds then close - await Task.Delay(3000); - Dialog?.CloseBootstrapper(); - - // keep bloxstrap open in the background if needed - if (!shouldWait) - return; - - activityWatcher?.StartWatcher(); - - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); - - while (Process.GetProcesses().Any(x => x.Id == gameClientPid)) - await Task.Delay(1000); - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Roblox has exited"); - - richPresence?.Dispose(); - - foreach (Process process in autocloseProcesses) - { - if (process.HasExited) - continue; - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); - process.Kill(); - } - } - - public void CancelInstall() - { - if (!_isInstalling) - { - App.Terminate(ERROR_INSTALL_USEREXIT); - return; - } - - App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); - - _cancelTokenSource.Cancel(); - _cancelFired = true; - - try - { - // clean up install - if (App.IsFirstRun) - Directory.Delete(Directories.Base, true); - else if (Directory.Exists(_versionFolder)) - Directory.Delete(_versionFolder, true); - } - catch (Exception ex) - { - App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); - App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {ex}"); - } - - App.Terminate(ERROR_INSTALL_USEREXIT); - } - #endregion - - #region App Install - public static void Register() - { - using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) - { - applicationKey.SetValue("InstallLocation", Directories.Base); - } - - // set uninstall key - using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")) - { - uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); - uninstallKey.SetValue("DisplayName", App.ProjectName); - uninstallKey.SetValue("DisplayVersion", App.Version); - - if (uninstallKey.GetValue("InstallDate") is null) - uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); - - uninstallKey.SetValue("InstallLocation", Directories.Base); - uninstallKey.SetValue("NoRepair", 1); - uninstallKey.SetValue("Publisher", "pizzaboxer"); - uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); - uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); - uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); - uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); - uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); - } - - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); - } - - public void RegisterProgramSize() - { - App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); - - using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); - - // sum compressed and uncompressed package sizes and convert to kilobytes - int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; - - uninstallKey.SetValue("EstimatedSize", totalSize); - - App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); - } - - private void CheckInstallMigration() - { - // check if we've changed our install location since the last time we started - // in which case, we'll have to copy over all our folders so we don't lose any mods and stuff - - using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true); - - string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation"); - - if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base) - return; - - SetStatus("Migrating install location..."); - - if (Directory.Exists(oldInstallLocation)) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}..."); - - foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories)) - { - string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1); - string newFileLocation = Path.Combine(Directories.Base, relativeFile); - string? newDirectory = Path.GetDirectoryName(newFileLocation); - - try - { - if (!String.IsNullOrEmpty(newDirectory)) - Directory.CreateDirectory(newDirectory); - - File.Move(oldFileLocation, newFileLocation, true); - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}"); - } - } - - try - { - Directory.Delete(oldInstallLocation, true); - App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location"); - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}"); - } - } - - applicationKey.DeleteValue("OldInstallLocation"); - - // allow shortcuts to be re-registered - if (Directory.Exists(Directories.StartMenu)) - Directory.Delete(Directories.StartMenu, true); - - if (File.Exists(DesktopShortcutLocation)) - { - File.Delete(DesktopShortcutLocation); - App.Settings.Prop.CreateDesktopIcon = true; - } - - App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!"); - } - - public static void CheckInstall() - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); - - // check if launch uri is set to our bootstrapper - // this doesn't go under register, so we check every launch - // just in case the stock bootstrapper changes it back - - ProtocolHandler.Register("roblox", "Roblox", Directories.Application); - ProtocolHandler.Register("roblox-player", "Roblox", Directories.Application); - - // in case the user is reinstalling - if (File.Exists(Directories.Application) && App.IsFirstRun) - File.Delete(Directories.Application); - - // check to make sure bootstrapper is in the install folder - if (!File.Exists(Directories.Application) && Environment.ProcessPath is not null) - File.Copy(Environment.ProcessPath, Directories.Application); - - // this SHOULD go under Register(), - // but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall - // maybe in a later version? - if (!Directory.Exists(Directories.StartMenu)) - { - Directory.CreateDirectory(Directories.StartMenu); - - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(Path.Combine(Directories.StartMenu, "Play Roblox.lnk")); - - ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) - .WriteToFile(Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk")); - } - else - { - // v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu" - string oldMenuShortcut = Path.Combine(Directories.StartMenu, $"Configure {App.ProjectName}.lnk"); - string newMenuShortcut = Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk"); - - if (File.Exists(oldMenuShortcut)) - File.Delete(oldMenuShortcut); - - if (!File.Exists(newMenuShortcut)) - ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) - .WriteToFile(newMenuShortcut); - } - - if (App.Settings.Prop.CreateDesktopIcon) - { - if (!File.Exists(DesktopShortcutLocation)) - { - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(DesktopShortcutLocation); - } - - // one-time toggle, set it back to false - App.Settings.Prop.CreateDesktopIcon = false; - } - } - - private async Task CheckForUpdates() - { - // don't update if there's another instance running (likely running in the background) - if (Utilities.GetProcessCount(App.ProjectName) > 1) - { - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); - return; - } - - string currentVersion = $"{App.ProjectName} v{App.Version}"; - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); - - var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); - - if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) - { - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); - return; - } - - SetStatus($"Getting the latest {App.ProjectName}..."); - - // 64-bit is always the first option - GithubReleaseAsset asset = releaseInfo.Assets[0]; - string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); - - if (!File.Exists(downloadLocation)) - { - var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl); - - await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); - } - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); - - ProcessStartInfo startInfo = new() - { - FileName = downloadLocation, - }; - - foreach (string arg in App.LaunchArgs) - startInfo.ArgumentList.Add(arg); - - App.Settings.Save(); - - Process.Start(startInfo); - - Environment.Exit(0); - } - - private void Uninstall() - { - // prompt to shutdown roblox if its currently running - if (Utilities.CheckIfRobloxRunning()) - { - App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); - - Dialog?.PromptShutdown(); - - try - { - foreach (Process process in Process.GetProcessesByName("RobloxPlayerBeta")) - { - process.CloseMainWindow(); - process.Close(); - } - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::ShutdownIfRobloxRunning] Failed to close process! {ex}"); - } - - App.Logger.WriteLine($"[Bootstrapper::Uninstall] All Roblox processes closed"); - } - - SetStatus($"Uninstalling {App.ProjectName}..."); - - //App.Settings.ShouldSave = false; - App.ShouldSaveConfigs = false; - - // check if stock bootstrapper is still installed - RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player"); - if (bootstrapperKey is null) - { - ProtocolHandler.Unregister("roblox"); - ProtocolHandler.Unregister("roblox-player"); - } - else - { - // revert launch uri handler to stock bootstrapper - - string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe"; - - ProtocolHandler.Register("roblox", "Roblox", bootstrapperLocation); - ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation); - } - - try - { - // delete application key - Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"); - - // delete start menu folder - Directory.Delete(Directories.StartMenu, true); - - // delete desktop shortcut - File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); - - // delete uninstall key - Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); - - // delete installation folder - // (should delete everything except bloxstrap itself) - Directory.Delete(Directories.Base, true); - } - catch (Exception ex) - { - App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); - } - - Action? callback = null; - - if (Directory.Exists(Directories.Base)) - { - callback = () => - { - // this is definitely one of the workaround hacks of all time - // could antiviruses falsely detect this as malicious behaviour though? - // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" - - Process.Start(new ProcessStartInfo() - { - FileName = "cmd.exe", - Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", - UseShellExecute = true, - WindowStyle = ProcessWindowStyle.Hidden - }); - }; - } - - Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); - } - #endregion - - #region Roblox Install - private async Task InstallLatestVersion() - { - _isInstalling = true; - - SetStatus(FreshInstall ? "Installing Roblox..." : "Upgrading Roblox..."); - - Directory.CreateDirectory(Directories.Base); - Directory.CreateDirectory(Directories.Downloads); - Directory.CreateDirectory(Directories.Versions); - - // package manifest states packed size and uncompressed size in exact bytes - // packed size only matters if we don't already have the package cached on disk - string[] cachedPackages = Directory.GetFiles(Directories.Downloads); - int totalSizeRequired = _versionPackageManifest.Where(x => !cachedPackages.Contains(x.Signature)).Sum(x => x.PackedSize) + _versionPackageManifest.Sum(x => x.Size); - - if (Utilities.GetFreeDiskSpace(Directories.Base) < totalSizeRequired) - { - App.ShowMessageBox($"{App.ProjectName} does not have enough disk space to download and install Roblox. Please free up some disk space and try again.", MessageBoxImage.Error); - App.Terminate(ERROR_INSTALL_FAILURE); - return; - } - - if (Dialog is not null) - { - Dialog.CancelEnabled = true; - Dialog.ProgressStyle = ProgressBarStyle.Continuous; - } - - // compute total bytes to download - _progressIncrement = (double)100 / _versionPackageManifest.Sum(package => package.PackedSize); - - foreach (Package package in _versionPackageManifest) - { - if (_cancelFired) - return; - - // download all the packages synchronously - await DownloadPackage(package); - - // we'll extract the runtime installer later if we need to - if (package.Name == "WebView2RuntimeInstaller.zip") - continue; - - // extract the package immediately after download asynchronously - // discard is just used to suppress the warning - Task _ = ExtractPackage(package); - } - - if (_cancelFired) - return; - - // allow progress bar to 100% before continuing (purely ux reasons lol) - await Task.Delay(1000); - - if (Dialog is not null) - { - Dialog.ProgressStyle = ProgressBarStyle.Marquee; - SetStatus("Configuring Roblox..."); - } - - // wait for all packages to finish extracting, with an exception for the webview2 runtime installer - while (_packagesExtracted < _versionPackageManifest.Where(x => x.Name != "WebView2RuntimeInstaller.zip").Count()) - { - await Task.Delay(100); - } - - string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); - await File.WriteAllTextAsync(appSettingsLocation, AppSettings); - - if (_cancelFired) - return; - - if (!FreshInstall) - { - // let's take this opportunity to delete any packages we don't need anymore - foreach (string filename in cachedPackages) - { - if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) - { - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); - File.Delete(filename); - } - } - - string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); - - // move old compatibility flags for the old location - using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) - { - string oldGameClientLocation = Path.Combine(oldVersionFolder, "RobloxPlayerBeta.exe"); - string? appFlags = (string?)appFlagsKey.GetValue(oldGameClientLocation); - - if (appFlags is not null) - { - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Migrating app compatibility flags from {oldGameClientLocation} to {_playerLocation}..."); - appFlagsKey.SetValue(_playerLocation, appFlags); - appFlagsKey.DeleteValue(oldGameClientLocation); - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows; + +using Microsoft.Win32; + +using Bloxstrap.Enums; +using Bloxstrap.Extensions; +using Bloxstrap.Integrations; +using Bloxstrap.Models; +using Bloxstrap.Tools; +using Bloxstrap.UI.BootstrapperDialogs; + +namespace Bloxstrap +{ + public class Bootstrapper + { + #region Properties + + // https://learn.microsoft.com/en-us/windows/win32/msi/error-codes + public const int ERROR_SUCCESS = 0; + public const int ERROR_INSTALL_USEREXIT = 1602; + public const int ERROR_INSTALL_FAILURE = 1603; + + // in case a new package is added, you can find the corresponding directory + // by opening the stock bootstrapper in a hex editor + // TODO - there ideally should be a less static way to do this that's not hardcoded? + private static readonly IReadOnlyDictionary PackageDirectories = new Dictionary() + { + { "RobloxApp.zip", @"" }, + { "shaders.zip", @"shaders\" }, + { "ssl.zip", @"ssl\" }, + + // the runtime installer is only extracted if it needs installing + { "WebView2.zip", @"" }, + { "WebView2RuntimeInstaller.zip", @"WebView2RuntimeInstaller\" }, + + { "content-avatar.zip", @"content\avatar\" }, + { "content-configs.zip", @"content\configs\" }, + { "content-fonts.zip", @"content\fonts\" }, + { "content-sky.zip", @"content\sky\" }, + { "content-sounds.zip", @"content\sounds\" }, + { "content-textures2.zip", @"content\textures\" }, + { "content-models.zip", @"content\models\" }, + + { "content-textures3.zip", @"PlatformContent\pc\textures\" }, + { "content-terrain.zip", @"PlatformContent\pc\terrain\" }, + { "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" }, + + { "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" }, + { "extracontent-translations.zip", @"ExtraContent\translations\" }, + { "extracontent-models.zip", @"ExtraContent\models\" }, + { "extracontent-textures.zip", @"ExtraContent\textures\" }, + { "extracontent-places.zip", @"ExtraContent\places\" }, + }; + + private const string AppSettings = + "\r\n" + + "\r\n" + + " content\r\n" + + " http://www.roblox.com\r\n" + + "\r\n"; + + private readonly CancellationTokenSource _cancelTokenSource = new(); + + private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); + private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); + + private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); + + private string _launchCommandLine; + + private string _latestVersionGuid = null!; + private PackageManifest _versionPackageManifest = null!; + private string _versionFolder = null!; + + private bool _isInstalling = false; + private double _progressIncrement; + private long _totalDownloadedBytes = 0; + private int _packagesExtracted = 0; + private bool _cancelFired = false; + + public IBootstrapperDialog? Dialog = null; + #endregion + + #region Core + public Bootstrapper(string launchCommandLine) + { + _launchCommandLine = launchCommandLine; + } + + private void SetStatus(string message) + { + App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); + + // yea idk + if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) + message = message.Replace("...", ""); + + if (Dialog is not null) + Dialog.Message = message; + } + + private void UpdateProgressbar() + { + int newProgress = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes); + + // bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100 + // too lazy to fix properly so lol + if (newProgress > 100) + return; + + if (Dialog is not null) + Dialog.ProgressValue = newProgress; + } + + public async Task Run() + { + App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); + + if (App.IsUninstall) + { + Uninstall(); + return; + } + +#if !DEBUG + if (!App.IsFirstRun && App.Settings.Prop.CheckForUpdates) + await CheckForUpdates(); +#endif + + // ensure only one instance of the bootstrapper is running at the time + // so that we don't have stuff like two updates happening simultaneously + + bool mutexExists = false; + + try + { + Mutex.OpenExisting("Bloxstrap_BootstrapperMutex").Close(); + App.Logger.WriteLine("[Bootstrapper::Run] Bloxstrap_BootstrapperMutex mutex exists, waiting..."); + mutexExists = true; + } + catch (Exception) + { + // no mutex exists + } + + // wait for mutex to be released if it's not yet + await using AsyncMutex mutex = new("Bloxstrap_BootstrapperMutex"); + await mutex.AcquireAsync(_cancelTokenSource.Token); + + // reload our configs since they've likely changed by now + if (mutexExists) + { + App.Settings.Load(); + App.State.Load(); + } + + await CheckLatestVersion(); + + CheckInstallMigration(); + + // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist + if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) + await InstallLatestVersion(); + + if (App.IsFirstRun) + App.ShouldSaveConfigs = true; + + MigrateIntegrations(); + + await InstallWebView2(); + + App.FastFlags.Save(); + await ApplyModifications(); + + if (App.IsFirstRun || FreshInstall) + { + Register(); + RegisterProgramSize(); + } + + CheckInstall(); + + // at this point we've finished updating our configs + App.Settings.Save(); + App.State.Save(); + App.ShouldSaveConfigs = false; + + await mutex.ReleaseAsync(); + + if (App.IsFirstRun && App.IsNoLaunch) + Dialog?.ShowSuccess($"{App.ProjectName} has successfully installed"); + else if (!App.IsNoLaunch && !_cancelFired) + await StartRoblox(); + } + + private async Task CheckLatestVersion() + { + SetStatus("Connecting to Roblox..."); + + ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); + + // briefly check if current channel is suitable to use + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) + { + string? switchDefaultPrompt = null; + ClientVersion? defaultChannelInfo = null; + + App.Logger.WriteLine($"[Bootstrapper::CheckLatestVersion] Checking if current channel is suitable to use..."); + + if (String.IsNullOrEmpty(switchDefaultPrompt)) + { + // this SUCKS + defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); + int defaultChannelVersion = Int32.Parse(defaultChannelInfo.Version.Split('.')[1]); + int currentChannelVersion = Int32.Parse(clientVersion.Version.Split('.')[1]); + + if (currentChannelVersion < defaultChannelVersion) + switchDefaultPrompt = $"Your current preferred channel ({App.Settings.Prop.Channel}) appears to no longer be receiving updates. Would you like to switch to {RobloxDeployment.DefaultChannel}?"; + } + + if (!String.IsNullOrEmpty(switchDefaultPrompt)) + { + MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox(switchDefaultPrompt, MessageBoxImage.Question, MessageBoxButton.YesNo); + + if (result == MessageBoxResult.Yes) + { + App.Settings.Prop.Channel = RobloxDeployment.DefaultChannel; + App.Logger.WriteLine($"[DeployManager::SwitchToDefault] Changed Roblox release channel from {App.Settings.Prop.Channel} to {RobloxDeployment.DefaultChannel}"); + + if (defaultChannelInfo is null) + defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); + + clientVersion = defaultChannelInfo; + } + } + } + + _latestVersionGuid = clientVersion.VersionGuid; + _versionFolder = Path.Combine(Directories.Versions, _latestVersionGuid); + _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); + } + + private async Task StartRoblox() + { + SetStatus("Starting Roblox..."); + + if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) + { + Utilities.OpenWebsite("https://www.roblox.com/games"); + Dialog?.CloseBootstrapper(); + return; + } + + _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); + + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) + _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); + + // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes + bool shouldWait = false; + + // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now + int gameClientPid; + using (Process gameClient = Process.Start(_playerLocation, _launchCommandLine)) + { + gameClientPid = gameClient.Id; + } + + List autocloseProcesses = new(); + RobloxActivity? activityWatcher = null; + DiscordRichPresence? richPresence = null; + ServerNotifier? serverNotifier = null; + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Started Roblox (PID {gameClientPid})"); + + using (SystemEvent startEvent = new("www.roblox.com/robloxStartedEvent")) + { + bool startEventFired = await startEvent.WaitForEvent(); + + startEvent.Close(); + + if (!startEventFired) + return; + } + + if (App.Settings.Prop.UseDiscordRichPresence || App.Settings.Prop.ShowServerDetails) + { + activityWatcher = new(); + shouldWait = true; + } + + if (App.Settings.Prop.UseDiscordRichPresence) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); + richPresence = new(activityWatcher!); + } + + if (App.Settings.Prop.ShowServerDetails) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using server details notifier"); + serverNotifier = new(activityWatcher!); + } + + // launch custom integrations now + foreach (CustomIntegration integration in App.Settings.Prop.CustomIntegrations) + { + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})"); + + try + { + Process process = Process.Start(integration.Location, integration.LaunchArgs); + + if (integration.AutoClose) + { + shouldWait = true; + autocloseProcesses.Add(process); + } + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Failed to launch integration '{integration.Name}'! ({ex.Message})"); + } + } + + // event fired, wait for 3 seconds then close + await Task.Delay(3000); + Dialog?.CloseBootstrapper(); + + // keep bloxstrap open in the background if needed + if (!shouldWait) + return; + + activityWatcher?.StartWatcher(); + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); + + while (Process.GetProcesses().Any(x => x.Id == gameClientPid)) + await Task.Delay(1000); + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Roblox has exited"); + + richPresence?.Dispose(); + + foreach (Process process in autocloseProcesses) + { + if (process.HasExited) + continue; + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); + process.Kill(); + } + } + + public void CancelInstall() + { + if (!_isInstalling) + { + App.Terminate(ERROR_INSTALL_USEREXIT); + return; + } + + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); + + _cancelTokenSource.Cancel(); + _cancelFired = true; + + try + { + // clean up install + if (App.IsFirstRun) + Directory.Delete(Directories.Base, true); + else if (Directory.Exists(_versionFolder)) + Directory.Delete(_versionFolder, true); + } + catch (Exception ex) + { + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); + App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {ex}"); + } + + App.Terminate(ERROR_INSTALL_USEREXIT); + } + #endregion + + #region App Install + public static void Register() + { + using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) + { + applicationKey.SetValue("InstallLocation", Directories.Base); + } + + // set uninstall key + using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")) + { + uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); + uninstallKey.SetValue("DisplayName", App.ProjectName); + uninstallKey.SetValue("DisplayVersion", App.Version); + + if (uninstallKey.GetValue("InstallDate") is null) + uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); + + uninstallKey.SetValue("InstallLocation", Directories.Base); + uninstallKey.SetValue("NoRepair", 1); + uninstallKey.SetValue("Publisher", "pizzaboxer"); + uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); + uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); + uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); + uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); + uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); + } + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); + } + + public void RegisterProgramSize() + { + App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); + + using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); + + // sum compressed and uncompressed package sizes and convert to kilobytes + int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; + + uninstallKey.SetValue("EstimatedSize", totalSize); + + App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); + } + + private void CheckInstallMigration() + { + // check if we've changed our install location since the last time we started + // in which case, we'll have to copy over all our folders so we don't lose any mods and stuff + + using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true); + + string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation"); + + if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base) + return; + + SetStatus("Migrating install location..."); + + if (Directory.Exists(oldInstallLocation)) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}..."); + + foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories)) + { + string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1); + string newFileLocation = Path.Combine(Directories.Base, relativeFile); + string? newDirectory = Path.GetDirectoryName(newFileLocation); + + try + { + if (!String.IsNullOrEmpty(newDirectory)) + Directory.CreateDirectory(newDirectory); + + File.Move(oldFileLocation, newFileLocation, true); + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}"); + } + } + + try + { + Directory.Delete(oldInstallLocation, true); + App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location"); + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}"); + } + } + + applicationKey.DeleteValue("OldInstallLocation"); + + // allow shortcuts to be re-registered + if (Directory.Exists(Directories.StartMenu)) + Directory.Delete(Directories.StartMenu, true); + + if (File.Exists(DesktopShortcutLocation)) + { + File.Delete(DesktopShortcutLocation); + App.Settings.Prop.CreateDesktopIcon = true; + } + + App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!"); + } + + public static void CheckInstall() + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); + + // check if launch uri is set to our bootstrapper + // this doesn't go under register, so we check every launch + // just in case the stock bootstrapper changes it back + + ProtocolHandler.Register("roblox", "Roblox", Directories.Application); + ProtocolHandler.Register("roblox-player", "Roblox", Directories.Application); + + // in case the user is reinstalling + if (File.Exists(Directories.Application) && App.IsFirstRun) + File.Delete(Directories.Application); + + // check to make sure bootstrapper is in the install folder + if (!File.Exists(Directories.Application) && Environment.ProcessPath is not null) + File.Copy(Environment.ProcessPath, Directories.Application); + + // this SHOULD go under Register(), + // but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall + // maybe in a later version? + if (!Directory.Exists(Directories.StartMenu)) + { + Directory.CreateDirectory(Directories.StartMenu); + + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(Path.Combine(Directories.StartMenu, "Play Roblox.lnk")); + + ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) + .WriteToFile(Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk")); + } + else + { + // v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu" + string oldMenuShortcut = Path.Combine(Directories.StartMenu, $"Configure {App.ProjectName}.lnk"); + string newMenuShortcut = Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk"); + + if (File.Exists(oldMenuShortcut)) + File.Delete(oldMenuShortcut); + + if (!File.Exists(newMenuShortcut)) + ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) + .WriteToFile(newMenuShortcut); + } + + if (App.Settings.Prop.CreateDesktopIcon) + { + if (!File.Exists(DesktopShortcutLocation)) + { + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(DesktopShortcutLocation); + } + + // one-time toggle, set it back to false + App.Settings.Prop.CreateDesktopIcon = false; + } + } + + private async Task CheckForUpdates() + { + // don't update if there's another instance running (likely running in the background) + if (Utilities.GetProcessCount(App.ProjectName) > 1) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); + return; + } + + string currentVersion = $"{App.ProjectName} v{App.Version}"; + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); + + var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); + + if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); + return; + } + + SetStatus($"Getting the latest {App.ProjectName}..."); + + // 64-bit is always the first option + GithubReleaseAsset asset = releaseInfo.Assets[0]; + string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); + + if (!File.Exists(downloadLocation)) + { + var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl); + + await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + } + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); + + ProcessStartInfo startInfo = new() + { + FileName = downloadLocation, + }; + + foreach (string arg in App.LaunchArgs) + startInfo.ArgumentList.Add(arg); + + App.Settings.Save(); + + Process.Start(startInfo); + + Environment.Exit(0); + } + + private void Uninstall() + { + // prompt to shutdown roblox if its currently running + if (Utilities.CheckIfRobloxRunning()) + { + App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); + + Dialog?.PromptShutdown(); + + try + { + foreach (Process process in Process.GetProcessesByName("RobloxPlayerBeta")) + { + process.CloseMainWindow(); + process.Close(); + } + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::ShutdownIfRobloxRunning] Failed to close process! {ex}"); + } + + App.Logger.WriteLine($"[Bootstrapper::Uninstall] All Roblox processes closed"); + } + + SetStatus($"Uninstalling {App.ProjectName}..."); + + //App.Settings.ShouldSave = false; + App.ShouldSaveConfigs = false; + + // check if stock bootstrapper is still installed + RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player"); + if (bootstrapperKey is null) + { + ProtocolHandler.Unregister("roblox"); + ProtocolHandler.Unregister("roblox-player"); + } + else + { + // revert launch uri handler to stock bootstrapper + + string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe"; + + ProtocolHandler.Register("roblox", "Roblox", bootstrapperLocation); + ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation); + } + + try + { + // delete application key + Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"); + + // delete start menu folder + Directory.Delete(Directories.StartMenu, true); + + // delete desktop shortcut + File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); + + // delete uninstall key + Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); + + // delete installation folder + // (should delete everything except bloxstrap itself) + Directory.Delete(Directories.Base, true); + } + catch (Exception ex) + { + App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); + } + + Action? callback = null; + + if (Directory.Exists(Directories.Base)) + { + callback = () => + { + // this is definitely one of the workaround hacks of all time + // could antiviruses falsely detect this as malicious behaviour though? + // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" + + Process.Start(new ProcessStartInfo() + { + FileName = "cmd.exe", + Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", + UseShellExecute = true, + WindowStyle = ProcessWindowStyle.Hidden + }); + }; + } + + Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); + } + #endregion + + #region Roblox Install + private async Task InstallLatestVersion() + { + _isInstalling = true; + + SetStatus(FreshInstall ? "Installing Roblox..." : "Upgrading Roblox..."); + + Directory.CreateDirectory(Directories.Base); + Directory.CreateDirectory(Directories.Downloads); + Directory.CreateDirectory(Directories.Versions); + + // package manifest states packed size and uncompressed size in exact bytes + // packed size only matters if we don't already have the package cached on disk + string[] cachedPackages = Directory.GetFiles(Directories.Downloads); + int totalSizeRequired = _versionPackageManifest.Where(x => !cachedPackages.Contains(x.Signature)).Sum(x => x.PackedSize) + _versionPackageManifest.Sum(x => x.Size); + + if (Utilities.GetFreeDiskSpace(Directories.Base) < totalSizeRequired) + { + App.ShowMessageBox($"{App.ProjectName} does not have enough disk space to download and install Roblox. Please free up some disk space and try again.", MessageBoxImage.Error); + App.Terminate(ERROR_INSTALL_FAILURE); + return; + } + + if (Dialog is not null) + { + Dialog.CancelEnabled = true; + Dialog.ProgressStyle = ProgressBarStyle.Continuous; + } + + // compute total bytes to download + _progressIncrement = (double)100 / _versionPackageManifest.Sum(package => package.PackedSize); + + foreach (Package package in _versionPackageManifest) + { + if (_cancelFired) + return; + + // download all the packages synchronously + await DownloadPackage(package); + + // we'll extract the runtime installer later if we need to + if (package.Name == "WebView2RuntimeInstaller.zip") + continue; + + // extract the package immediately after download asynchronously + // discard is just used to suppress the warning + Task _ = ExtractPackage(package); + } + + if (_cancelFired) + return; + + // allow progress bar to 100% before continuing (purely ux reasons lol) + await Task.Delay(1000); + + if (Dialog is not null) + { + Dialog.ProgressStyle = ProgressBarStyle.Marquee; + SetStatus("Configuring Roblox..."); + } + + // wait for all packages to finish extracting, with an exception for the webview2 runtime installer + while (_packagesExtracted < _versionPackageManifest.Where(x => x.Name != "WebView2RuntimeInstaller.zip").Count()) + { + await Task.Delay(100); + } + + string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); + await File.WriteAllTextAsync(appSettingsLocation, AppSettings); + + if (_cancelFired) + return; + + if (!FreshInstall) + { + // let's take this opportunity to delete any packages we don't need anymore + foreach (string filename in cachedPackages) + { + if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) + { + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); + File.Delete(filename); + } + } + + string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); + + // move old compatibility flags for the old location + using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) + { + string oldGameClientLocation = Path.Combine(oldVersionFolder, "RobloxPlayerBeta.exe"); + string? appFlags = (string?)appFlagsKey.GetValue(oldGameClientLocation); + + if (appFlags is not null) + { + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Migrating app compatibility flags from {oldGameClientLocation} to {_playerLocation}..."); + appFlagsKey.SetValue(_playerLocation, appFlags); + appFlagsKey.DeleteValue(oldGameClientLocation); + } } // delete any old version folders // we only do this if roblox isnt running just in case an update happened // while they were launching a second instance or something idk - if (!Process.GetProcessesByName(App.RobloxAppName).Any()) - { - foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) - { - if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) - continue; - - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); - dir.Delete(true); - } - } - } - - App.State.Prop.VersionGuid = _latestVersionGuid; - - // don't register program size until the program is registered, which will be done after this - if (!App.IsFirstRun && !FreshInstall) - RegisterProgramSize(); - - if (Dialog is not null) - Dialog.CancelEnabled = false; - - _isInstalling = false; - } - - private async Task InstallWebView2() - { - // check if the webview2 runtime needs to be installed - // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu - // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed - - using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - using RegistryKey? hkcuKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - - if (hklmKey is not null || hkcuKey is not null) - return; - - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); - - string baseDirectory = Path.Combine(_versionFolder, "WebView2RuntimeInstaller"); - - if (!Directory.Exists(baseDirectory)) - { - Package? package = _versionPackageManifest.Find(x => x.Name == "WebView2RuntimeInstaller.zip"); - - if (package is null) - { - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Aborted runtime install because package does not exist, has WebView2 been added in this Roblox version yet?"); - return; - } - - await ExtractPackage(package); - } - - SetStatus("Installing WebView2, please wait..."); - - ProcessStartInfo startInfo = new() - { - WorkingDirectory = baseDirectory, - FileName = Path.Combine(baseDirectory, "MicrosoftEdgeWebview2Setup.exe"), - Arguments = "/silent /install" - }; - - await Process.Start(startInfo)!.WaitForExitAsync(); - - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Finished installing runtime"); - } - - public static void MigrateIntegrations() - { - // v2.2.0 - remove rbxfpsunlocker - string rbxfpsunlocker = Path.Combine(Directories.Integrations, "rbxfpsunlocker"); - - if (Directory.Exists(rbxfpsunlocker)) - Directory.Delete(rbxfpsunlocker, true); - - // v2.3.0 - remove reshade - string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); - string configLocation = Path.Combine(Directories.Modifications, "ReShade.ini"); - - if (File.Exists(injectorLocation)) - { - App.ShowMessageBox( - "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ - "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", - MessageBoxImage.Warning - ); - - File.Delete(injectorLocation); - } - - if (File.Exists(configLocation)) - File.Delete(configLocation); - } - - private async Task ApplyModifications() - { - SetStatus("Applying Roblox modifications..."); - - // set executable flags for fullscreen optimizations - App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking executable flags..."); - using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) - { - const string flag = " DISABLEDXMAXIMIZEDWINDOWEDMODE"; - string? appFlags = (string?)appFlagsKey.GetValue(_playerLocation); - - if (App.Settings.Prop.DisableFullscreenOptimizations) - { - if (appFlags is null) - appFlagsKey.SetValue(_playerLocation, $"~{flag}"); - else if (!appFlags.Contains(flag)) - appFlagsKey.SetValue(_playerLocation, appFlags + flag); - } - else if (appFlags is not null && appFlags.Contains(flag)) - { - // if there's more than one space, there's more flags set we need to preserve - if (appFlags.Split(' ').Length > 2) - appFlagsKey.SetValue(_playerLocation, appFlags.Remove(appFlags.IndexOf(flag), flag.Length)); - else - appFlagsKey.DeleteValue(_playerLocation); - } - } - - // handle file mods - App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking file mods..."); - string modFolder = Path.Combine(Directories.Modifications); - - // manifest has been moved to State.json - File.Delete(Path.Combine(Directories.Base, "ModManifest.txt")); - - List modFolderFiles = new(); - - if (!Directory.Exists(modFolder)) - Directory.CreateDirectory(modFolder); - - await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseDisableAppPatch, @"ExtraContent\places\Mobile.rbxl", ""); - - // emoji presets are downloaded remotely from github due to how large they are - string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); - - if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) - { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - App.State.Prop.CurrentEmojiType = EmojiType.Default; - } - else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) - { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); - - var response = await App.HttpClient.GetAsync(remoteEmojiLocation); - await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); - - App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; - } - - foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) - { - // get relative directory path - string relativeFile = file.Substring(modFolder.Length + 1); - - // v1.7.0 - README has been moved to the preferences menu now - if (relativeFile == "README.txt") - { - File.Delete(file); - continue; - } - - modFolderFiles.Add(relativeFile); - } - - // copy and overwrite - foreach (string file in modFolderFiles) - { - string fileModFolder = Path.Combine(modFolder, file); - string fileVersionFolder = Path.Combine(_versionFolder, file); - - if (File.Exists(fileVersionFolder)) - { - if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) - continue; - } - - string? directory = Path.GetDirectoryName(fileVersionFolder); - - if (directory is null) - continue; - - Directory.CreateDirectory(directory); - - File.Copy(fileModFolder, fileVersionFolder, true); - File.SetAttributes(fileVersionFolder, File.GetAttributes(fileModFolder) & ~FileAttributes.ReadOnly); - } - - // the manifest is primarily here to keep track of what files have been - // deleted from the modifications folder, so that we know when to restore the original files from the downloaded packages - // now check for files that have been deleted from the mod folder according to the manifest - foreach (string fileLocation in App.State.Prop.ModManifest) - { - if (modFolderFiles.Contains(fileLocation)) - continue; - - KeyValuePair packageDirectory; - - try - { - packageDirectory = PackageDirectories.First(x => x.Value != "" && fileLocation.StartsWith(x.Value)); - } - catch (InvalidOperationException) - { - // package doesn't exist, likely mistakenly placed file - string versionFileLocation = Path.Combine(_versionFolder, fileLocation); - - if (File.Exists(versionFileLocation)) - File.Delete(versionFileLocation); - - continue; - } - - // restore original file - string fileName = fileLocation.Substring(packageDirectory.Value.Length); - ExtractFileFromPackage(packageDirectory.Key, fileName); - } - - App.State.Prop.ModManifest = modFolderFiles; - App.State.Save(); - } - - private static async Task CheckModPreset(bool condition, string location, string name) - { - string modFolderLocation = Path.Combine(Directories.Modifications, location); - byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); - - if (condition) - { - if (!File.Exists(modFolderLocation)) - { - string? directory = Path.GetDirectoryName(modFolderLocation); - - if (directory is null) - return; - - Directory.CreateDirectory(directory); - - await File.WriteAllBytesAsync(modFolderLocation, binaryData); - } - } - else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) - { - File.Delete(modFolderLocation); - } - } - - private async Task DownloadPackage(Package package) - { - if (_cancelFired) - return; - - string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}"); - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string robloxPackageLocation = Path.Combine(Directories.LocalAppData, "Roblox", "Downloads", package.Signature); - - if (File.Exists(packageLocation)) - { - FileInfo file = new(packageLocation); - - string calculatedMD5 = Utilities.MD5File(packageLocation); - if (calculatedMD5 != package.Signature) - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); - file.Delete(); - } - else - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); - _totalDownloadedBytes += package.PackedSize; - UpdateProgressbar(); - return; - } - } - else if (File.Exists(robloxPackageLocation)) - { - // let's cheat! if the stock bootstrapper already previously downloaded the file, - // then we can just copy the one from there - - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); - File.Copy(robloxPackageLocation, packageLocation); - _totalDownloadedBytes += package.PackedSize; - UpdateProgressbar(); - return; - } - - if (!File.Exists(packageLocation)) - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); - - { - var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); - var buffer = new byte[4096]; - - await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token); - await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete); - - while (true) - { - if (_cancelFired) - { - stream.Close(); - fileStream.Close(); - return; - } - - var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cancelTokenSource.Token); - - if (bytesRead == 0) - break; // we're done - - await fileStream.WriteAsync(buffer, 0, bytesRead, _cancelTokenSource.Token); - - _totalDownloadedBytes += bytesRead; - UpdateProgressbar(); - } - } - - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); - } - } - - private async Task ExtractPackage(Package package) - { - if (_cancelFired) - return; - - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); - string extractPath; - - App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); - - using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) - { - foreach (ZipArchiveEntry entry in archive.Entries) - { - if (_cancelFired) - return; - - if (entry.FullName.EndsWith('\\')) - continue; - - extractPath = Path.Combine(packageFolder, entry.FullName); - - //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); - - string? directory = Path.GetDirectoryName(extractPath); - - if (directory is null) - continue; - - Directory.CreateDirectory(directory); - - await Task.Run(() => entry.ExtractToFile(extractPath, true)); - } - } - - App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); - - _packagesExtracted += 1; - } - - private void ExtractFileFromPackage(string packageName, string fileName) - { - Package? package = _versionPackageManifest.Find(x => x.Name == packageName); - - if (package is null) - return; - - DownloadPackage(package).GetAwaiter().GetResult(); - - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); - - using ZipArchive archive = ZipFile.OpenRead(packageLocation); - - ZipArchiveEntry? entry = archive.Entries.FirstOrDefault(x => x.FullName == fileName); - - if (entry is null) - return; - - string fileLocation = Path.Combine(packageFolder, entry.FullName); - - File.Delete(fileLocation); - - entry.ExtractToFile(fileLocation); - } - #endregion - } -} + if (!Process.GetProcessesByName(App.RobloxAppName).Any()) + { + foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) + { + if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) + continue; + + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); + dir.Delete(true); + } + } + } + + App.State.Prop.VersionGuid = _latestVersionGuid; + + // don't register program size until the program is registered, which will be done after this + if (!App.IsFirstRun && !FreshInstall) + RegisterProgramSize(); + + if (Dialog is not null) + Dialog.CancelEnabled = false; + + _isInstalling = false; + } + + private async Task InstallWebView2() + { + // check if the webview2 runtime needs to be installed + // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu + // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed + + using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + using RegistryKey? hkcuKey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + + if (hklmKey is not null || hkcuKey is not null) + return; + + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); + + string baseDirectory = Path.Combine(_versionFolder, "WebView2RuntimeInstaller"); + + if (!Directory.Exists(baseDirectory)) + { + Package? package = _versionPackageManifest.Find(x => x.Name == "WebView2RuntimeInstaller.zip"); + + if (package is null) + { + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Aborted runtime install because package does not exist, has WebView2 been added in this Roblox version yet?"); + return; + } + + await ExtractPackage(package); + } + + SetStatus("Installing WebView2, please wait..."); + + ProcessStartInfo startInfo = new() + { + WorkingDirectory = baseDirectory, + FileName = Path.Combine(baseDirectory, "MicrosoftEdgeWebview2Setup.exe"), + Arguments = "/silent /install" + }; + + await Process.Start(startInfo)!.WaitForExitAsync(); + + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Finished installing runtime"); + } + + public static void MigrateIntegrations() + { + // v2.2.0 - remove rbxfpsunlocker + string rbxfpsunlocker = Path.Combine(Directories.Integrations, "rbxfpsunlocker"); + + if (Directory.Exists(rbxfpsunlocker)) + Directory.Delete(rbxfpsunlocker, true); + + // v2.3.0 - remove reshade + string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); + string configLocation = Path.Combine(Directories.Modifications, "ReShade.ini"); + + if (File.Exists(injectorLocation)) + { + App.ShowMessageBox( + "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ + "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", + MessageBoxImage.Warning + ); + + File.Delete(injectorLocation); + } + + if (File.Exists(configLocation)) + File.Delete(configLocation); + } + + private async Task ApplyModifications() + { + SetStatus("Applying Roblox modifications..."); + + // set executable flags for fullscreen optimizations + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking executable flags..."); + using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) + { + const string flag = " DISABLEDXMAXIMIZEDWINDOWEDMODE"; + string? appFlags = (string?)appFlagsKey.GetValue(_playerLocation); + + if (App.Settings.Prop.DisableFullscreenOptimizations) + { + if (appFlags is null) + appFlagsKey.SetValue(_playerLocation, $"~{flag}"); + else if (!appFlags.Contains(flag)) + appFlagsKey.SetValue(_playerLocation, appFlags + flag); + } + else if (appFlags is not null && appFlags.Contains(flag)) + { + // if there's more than one space, there's more flags set we need to preserve + if (appFlags.Split(' ').Length > 2) + appFlagsKey.SetValue(_playerLocation, appFlags.Remove(appFlags.IndexOf(flag), flag.Length)); + else + appFlagsKey.DeleteValue(_playerLocation); + } + } + + // handle file mods + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking file mods..."); + string modFolder = Path.Combine(Directories.Modifications); + + // manifest has been moved to State.json + File.Delete(Path.Combine(Directories.Base, "ModManifest.txt")); + + List modFolderFiles = new(); + + if (!Directory.Exists(modFolder)) + Directory.CreateDirectory(modFolder); + + await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); + await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); + await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseDisableAppPatch, @"ExtraContent\places\Mobile.rbxl", ""); + + // emoji presets are downloaded remotely from github due to how large they are + string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); + + if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + App.State.Prop.CurrentEmojiType = EmojiType.Default; + } + else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); + + var response = await App.HttpClient.GetAsync(remoteEmojiLocation); + await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + + App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; + } + + foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) + { + // get relative directory path + string relativeFile = file.Substring(modFolder.Length + 1); + + // v1.7.0 - README has been moved to the preferences menu now + if (relativeFile == "README.txt") + { + File.Delete(file); + continue; + } + + modFolderFiles.Add(relativeFile); + } + + // copy and overwrite + foreach (string file in modFolderFiles) + { + string fileModFolder = Path.Combine(modFolder, file); + string fileVersionFolder = Path.Combine(_versionFolder, file); + + if (File.Exists(fileVersionFolder)) + { + if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) + continue; + } + + string? directory = Path.GetDirectoryName(fileVersionFolder); + + if (directory is null) + continue; + + Directory.CreateDirectory(directory); + + File.Copy(fileModFolder, fileVersionFolder, true); + File.SetAttributes(fileVersionFolder, File.GetAttributes(fileModFolder) & ~FileAttributes.ReadOnly); + } + + // the manifest is primarily here to keep track of what files have been + // deleted from the modifications folder, so that we know when to restore the original files from the downloaded packages + // now check for files that have been deleted from the mod folder according to the manifest + foreach (string fileLocation in App.State.Prop.ModManifest) + { + if (modFolderFiles.Contains(fileLocation)) + continue; + + KeyValuePair packageDirectory; + + try + { + packageDirectory = PackageDirectories.First(x => x.Value != "" && fileLocation.StartsWith(x.Value)); + } + catch (InvalidOperationException) + { + // package doesn't exist, likely mistakenly placed file + string versionFileLocation = Path.Combine(_versionFolder, fileLocation); + + if (File.Exists(versionFileLocation)) + File.Delete(versionFileLocation); + + continue; + } + + // restore original file + string fileName = fileLocation.Substring(packageDirectory.Value.Length); + ExtractFileFromPackage(packageDirectory.Key, fileName); + } + + App.State.Prop.ModManifest = modFolderFiles; + App.State.Save(); + } + + private static async Task CheckModPreset(bool condition, string location, string name) + { + string modFolderLocation = Path.Combine(Directories.Modifications, location); + byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); + + if (condition) + { + if (!File.Exists(modFolderLocation)) + { + string? directory = Path.GetDirectoryName(modFolderLocation); + + if (directory is null) + return; + + Directory.CreateDirectory(directory); + + await File.WriteAllBytesAsync(modFolderLocation, binaryData); + } + } + else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) + { + File.Delete(modFolderLocation); + } + } + + private async Task DownloadPackage(Package package) + { + if (_cancelFired) + return; + + string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}"); + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string robloxPackageLocation = Path.Combine(Directories.LocalAppData, "Roblox", "Downloads", package.Signature); + + if (File.Exists(packageLocation)) + { + FileInfo file = new(packageLocation); + + string calculatedMD5 = Utilities.MD5File(packageLocation); + if (calculatedMD5 != package.Signature) + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); + file.Delete(); + } + else + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); + _totalDownloadedBytes += package.PackedSize; + UpdateProgressbar(); + return; + } + } + else if (File.Exists(robloxPackageLocation)) + { + // let's cheat! if the stock bootstrapper already previously downloaded the file, + // then we can just copy the one from there + + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); + File.Copy(robloxPackageLocation, packageLocation); + _totalDownloadedBytes += package.PackedSize; + UpdateProgressbar(); + return; + } + + if (!File.Exists(packageLocation)) + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); + + { + var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); + var buffer = new byte[4096]; + + await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token); + await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete); + + while (true) + { + if (_cancelFired) + { + stream.Close(); + fileStream.Close(); + return; + } + + var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cancelTokenSource.Token); + + if (bytesRead == 0) + break; // we're done + + await fileStream.WriteAsync(buffer, 0, bytesRead, _cancelTokenSource.Token); + + _totalDownloadedBytes += bytesRead; + UpdateProgressbar(); + } + } + + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); + } + } + + private async Task ExtractPackage(Package package) + { + if (_cancelFired) + return; + + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); + string extractPath; + + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); + + using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) + { + foreach (ZipArchiveEntry entry in archive.Entries) + { + if (_cancelFired) + return; + + if (entry.FullName.EndsWith('\\')) + continue; + + extractPath = Path.Combine(packageFolder, entry.FullName); + + //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); + + string? directory = Path.GetDirectoryName(extractPath); + + if (directory is null) + continue; + + Directory.CreateDirectory(directory); + + await Task.Run(() => entry.ExtractToFile(extractPath, true)); + } + } + + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); + + _packagesExtracted += 1; + } + + private void ExtractFileFromPackage(string packageName, string fileName) + { + Package? package = _versionPackageManifest.Find(x => x.Name == packageName); + + if (package is null) + return; + + DownloadPackage(package).GetAwaiter().GetResult(); + + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); + + using ZipArchive archive = ZipFile.OpenRead(packageLocation); + + ZipArchiveEntry? entry = archive.Entries.FirstOrDefault(x => x.FullName == fileName); + + if (entry is null) + return; + + string fileLocation = Path.Combine(packageFolder, entry.FullName); + + File.Delete(fileLocation); + + entry.ExtractToFile(fileLocation); + } + #endregion + } +} From 324859521e742f69d7adfa7ab7f5b7d405156cd3 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 17:42:38 +0100 Subject: [PATCH 056/178] Line ending normalization --- Bloxstrap/Bootstrapper.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 7cf2a02d..c98bd988 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -806,11 +806,11 @@ private async Task InstallLatestVersion() appFlagsKey.SetValue(_playerLocation, appFlags); appFlagsKey.DeleteValue(oldGameClientLocation); } - } - - // delete any old version folders - // we only do this if roblox isnt running just in case an update happened - // while they were launching a second instance or something idk + } + + // delete any old version folders + // we only do this if roblox isnt running just in case an update happened + // while they were launching a second instance or something idk if (!Process.GetProcessesByName(App.RobloxAppName).Any()) { foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) From 1232501698f84eff42bf2f0e4a46d2d651d10500 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 17:43:14 +0100 Subject: [PATCH 057/178] Fix WebView2 check --- Bloxstrap/Bootstrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index c98bd988..79f78f18 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -843,7 +843,7 @@ private async Task InstallWebView2() // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - using RegistryKey? hkcuKey = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + using RegistryKey? hkcuKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); if (hklmKey is not null || hkcuKey is not null) return; From 9aded4ead5570ea9d59d24d727d617948d8b300d Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 20:43:48 +0100 Subject: [PATCH 058/178] Remove option for the 2021/v3 escape menu (#328) rip :( --- Bloxstrap/Singletons/FastFlagManager.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index 191c645c..521b7972 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -45,7 +45,6 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", null }, - { "FFlagEnableInGameMenuV3", null }, { "FFlagEnableInGameMenuControls", null }, { "FFlagEnableV3MenuABTest3", null }, { "FFlagEnableMenuControlsABTest", null } @@ -57,7 +56,6 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", "True" }, - { "FFlagEnableInGameMenuV3", "False" }, { "FFlagEnableInGameMenuControls", "False" }, { "FFlagEnableV3MenuABTest3", "False" }, { "FFlagEnableMenuControlsABTest", "False" } @@ -69,19 +67,6 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", "False" }, - { "FFlagEnableInGameMenuV3", "False" }, - { "FFlagEnableInGameMenuControls", "False" }, - { "FFlagEnableV3MenuABTest3", "False" }, - { "FFlagEnableMenuControlsABTest", "False" } - } - }, - - { - "Version 3 (2021)", - new Dictionary - { - { "FFlagDisableNewIGMinDUA", "False" }, - { "FFlagEnableInGameMenuV3", "True" }, { "FFlagEnableInGameMenuControls", "False" }, { "FFlagEnableV3MenuABTest3", "False" }, { "FFlagEnableMenuControlsABTest", "False" } @@ -93,7 +78,6 @@ public class FastFlagManager : JsonManager> new Dictionary { { "FFlagDisableNewIGMinDUA", "True" }, - { "FFlagEnableInGameMenuV3", "False" }, { "FFlagEnableInGameMenuControls", "True" }, { "FFlagEnableV3MenuABTest3", "True" }, { "FFlagEnableMenuControlsABTest", "True" } From 14a18726744d9210bda9eb1363cc01c94ae5a08f Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 20:46:30 +0100 Subject: [PATCH 059/178] Disambiguate options for lighting mode selection --- Bloxstrap/Singletons/FastFlagManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index 521b7972..788f90c2 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -30,10 +30,10 @@ public class FastFlagManager : JsonManager> public static IReadOnlyDictionary LightingTechnologies => new Dictionary { - { "Automatic", "" }, - { "Voxel", "DFFlagDebugRenderForceTechnologyVoxel" }, - { "ShadowMap", "FFlagDebugForceFutureIsBrightPhase2" }, - { "Future", "FFlagDebugForceFutureIsBrightPhase3" } + { "Chosen by game", "" }, + { "Voxel (Phase 1)", "DFFlagDebugRenderForceTechnologyVoxel" }, + { "ShadowMap (Phase 2)", "FFlagDebugForceFutureIsBrightPhase2" }, + { "Future (Phase 3)", "FFlagDebugForceFutureIsBrightPhase3" } }; // this is one hell of a dictionary definition lmao From 670790a0236624144c808c7514d77b752f1d954e Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 21:36:07 +0100 Subject: [PATCH 060/178] Enable D3D exclusive fullscreen by default --- Bloxstrap/Singletons/FastFlagManager.cs | 51 +++++++------------ .../UI/Menu/ViewModels/FastFlagsViewModel.cs | 33 +++++------- .../UI/Menu/Views/Pages/FastFlagsPage.xaml | 9 ---- 3 files changed, 32 insertions(+), 61 deletions(-) diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/Singletons/FastFlagManager.cs index 788f90c2..f0ee4d01 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/Singletons/FastFlagManager.cs @@ -22,9 +22,9 @@ public class FastFlagManager : JsonManager> public static IReadOnlyDictionary RenderingModes => new Dictionary { { "Automatic", "" }, + { "Vulkan", "FFlagDebugGraphicsPreferVulkan" }, { "Direct3D 11", "FFlagDebugGraphicsPreferD3D11" }, { "Direct3D 10", "FFlagDebugGraphicsPreferD3D11FL10" }, - { "Vulkan", "FFlagDebugGraphicsPreferVulkan" }, { "OpenGL", "FFlagDebugGraphicsPreferOpenGL" } }; @@ -101,6 +101,22 @@ public void SetValue(string key, object? value) } } + // this will set the flag to the corresponding value if the condition is true + // if the condition is not true, the flag will be erased + public void SetValueIf(bool condition, string key, object? value) + { + if (condition) + SetValue(key, value); + else if (GetValue(key) is not null) + SetValue(key, null); + } + + public void SetValueOnce(string key, object? value) + { + if (GetValue(key) is null) + SetValue(key, value); + } + // this returns null if the fflag doesn't exist public string? GetValue(string key) { @@ -114,42 +130,13 @@ public void SetValue(string key, object? value) return null; } - public void SetRenderingMode(string value) - { - foreach (var mode in RenderingModes) - { - if (mode.Key != "Automatic") - SetValue(mode.Value, null); - } - - if (value != "Automatic") - SetValue(RenderingModes[value], "True"); - - if (value == "Vulkan") - SetValue("FFlagRenderVulkanFixMinimizeWindow", "True"); - else if (GetValue("FFlagRenderVulkanFixMinimizeWindow") is not null) - SetValue("FFlagRenderVulkanFixMinimizeWindow", null); - } - public override void Load() { base.Load(); // set to 9999 by default if it doesnt already exist - if (GetValue("DFIntTaskSchedulerTargetFps") is null) - SetValue("DFIntTaskSchedulerTargetFps", 9999); - - if (GetValue("FFlagDebugGraphicsPreferVulkan") == "True" && GetValue("FFlagRenderVulkanFixMinimizeWindow") is null) - SetValue("FFlagRenderVulkanFixMinimizeWindow", "True"); - - // exclusive fullscreen requires direct3d 10/11 to work - if (App.FastFlags.GetValue("FFlagHandleAltEnterFullscreenManually") == "False") - { - if (!(App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11") == "True" || App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11FL10") == "True")) - { - SetRenderingMode("Direct3D 11"); - } - } + SetValueOnce("DFIntTaskSchedulerTargetFps", 9999); + SetValueOnce("FFlagHandleAltEnterFullscreenManually", "False"); } public override void Save() diff --git a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs index d5ccc5e8..ce1e3018 100644 --- a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs @@ -40,26 +40,19 @@ public string SelectedRenderingMode return "Automatic"; } - set => App.FastFlags.SetRenderingMode(value); - } - - // this flag has to be set to false to work, weirdly enough - public bool ExclusiveFullscreenEnabled - { - get => App.FastFlags.GetValue("FFlagHandleAltEnterFullscreenManually") == "False"; - set - { - App.FastFlags.SetValue("FFlagHandleAltEnterFullscreenManually", value ? "False" : null); - - if (value) - { - if (!(App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11") == "True" || App.FastFlags.GetValue("FFlagDebugGraphicsPreferD3D11FL10") == "True")) - { - App.FastFlags.SetRenderingMode("Direct3D 11"); - } - - OnPropertyChanged(nameof(SelectedRenderingMode)); - } + set + { + foreach (var mode in RenderingModes) + { + if (mode.Key != "Automatic") + App.FastFlags.SetValue(mode.Value, null); + } + + if (value == "Automatic") + return; + + App.FastFlags.SetValue(RenderingModes[value], "True"); + App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True"); } } diff --git a/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml index 5977714d..d7a130e3 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml @@ -98,15 +98,6 @@ - - - - - - - - - From 09d20ac42771f6bd227d61db0baebb94ad954bdb Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 21:50:47 +0100 Subject: [PATCH 061/178] Add installation path check (#314) --- .../UI/Menu/ViewModels/InstallationViewModel.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs index 0fd9fade..e3ca027c 100644 --- a/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; @@ -65,11 +66,15 @@ private void BrowseInstallLocation() { using var dialog = new FolderBrowserDialog(); - if (dialog.ShowDialog() == DialogResult.OK) - { + if (dialog.ShowDialog() != DialogResult.OK) + return; + + if (!dialog.SelectedPath.EndsWith(App.ProjectName)) + InstallLocation = Path.Combine(dialog.SelectedPath, App.ProjectName); + else InstallLocation = dialog.SelectedPath; - OnPropertyChanged(nameof(InstallLocation)); - } + + OnPropertyChanged(nameof(InstallLocation)); } private void OpenFolder() From 28bcf57dff18c88255daff8c879e2aae6659cf43 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 22:06:40 +0100 Subject: [PATCH 062/178] Re-enable desktop app if launching with deeplink --- Bloxstrap/App.xaml.cs | 3 +++ Bloxstrap/Bootstrapper.cs | 2 +- Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index d49ad31c..28909723 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -253,6 +253,9 @@ protected override void OnStartup(StartupEventArgs e) } else if (LaunchArgs[0].StartsWith("roblox:")) { + if (Settings.Prop.UseDisableAppPatch) + ShowMessageBox("Roblox was launched via a deeplink, however the desktop app is required for deeplink launching to work. Because you've opted to disable the desktop app, it will temporarily be re-enabled for this launch only.", MessageBoxImage.Information); + commandLine = $"--app --deeplink {LaunchArgs[0]}"; } else diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 79f78f18..a52d8852 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -955,7 +955,7 @@ private async Task ApplyModifications() await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseDisableAppPatch, @"ExtraContent\places\Mobile.rbxl", ""); + await CheckModPreset(App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"), @"ExtraContent\places\Mobile.rbxl", ""); // emoji presets are downloaded remotely from github due to how large they are string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); diff --git a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml index 57dd470e..7c801c4f 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml @@ -103,7 +103,7 @@ - + From e7fd0b964217e9ac338de8b5707210fe009076db Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 22:33:15 +0100 Subject: [PATCH 063/178] Minor restructuring --- Bloxstrap/App.xaml.cs | 4 +- Bloxstrap/Bootstrapper.cs | 13 +- Bloxstrap/{Singletons => }/FastFlagManager.cs | 18 +- Bloxstrap/{Singletons => }/JsonManager.cs | 2 +- Bloxstrap/{Singletons => }/Logger.cs | 2 +- .../WinForms/DialogBase.cs | 2 + .../UI/Menu/ViewModels/FastFlagsViewModel.cs | 35 ++- .../UI/Menu/ViewModels/GlobalViewModel.cs | 2 +- Bloxstrap/Updater.cs | 2 +- Bloxstrap/Utilities.cs | 60 +----- Bloxstrap/{Tools => Utility}/AsyncMutex.cs | 204 +++++++++--------- Bloxstrap/Utility/MD5Hash.cs | 34 +++ Bloxstrap/{ => Utility}/NativeMethods.cs | 4 +- Bloxstrap/{Tools => Utility}/SystemEvent.cs | 94 ++++---- Bloxstrap/{ => Utility}/WindowScaling.cs | 65 +++--- 15 files changed, 256 insertions(+), 285 deletions(-) rename Bloxstrap/{Singletons => }/FastFlagManager.cs (98%) rename Bloxstrap/{Singletons => }/JsonManager.cs (98%) rename Bloxstrap/{Singletons => }/Logger.cs (98%) rename Bloxstrap/{Tools => Utility}/AsyncMutex.cs (97%) create mode 100644 Bloxstrap/Utility/MD5Hash.cs rename Bloxstrap/{ => Utility}/NativeMethods.cs (91%) rename Bloxstrap/{Tools => Utility}/SystemEvent.cs (96%) rename Bloxstrap/{ => Utility}/WindowScaling.cs (78%) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 28909723..affaefaf 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -15,10 +15,10 @@ using Bloxstrap.Extensions; using Bloxstrap.Models; -using Bloxstrap.Singletons; using Bloxstrap.UI.BootstrapperDialogs; using Bloxstrap.UI.Menu.Views; - +using Bloxstrap.Utility; + namespace Bloxstrap { ///

diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index a52d8852..66cfddc0 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -256,7 +256,7 @@ private async Task StartRoblox() if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) { - Utilities.OpenWebsite("https://www.roblox.com/games"); + Utilities.ShellExecute("https://www.roblox.com/games"); Dialog?.CloseBootstrapper(); return; } @@ -562,7 +562,7 @@ public static void CheckInstall() private async Task CheckForUpdates() { // don't update if there's another instance running (likely running in the background) - if (Utilities.GetProcessCount(App.ProjectName) > 1) + if (Process.GetProcessesByName(App.ProjectName).Count() > 1) { App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); return; @@ -616,7 +616,7 @@ private async Task CheckForUpdates() private void Uninstall() { // prompt to shutdown roblox if its currently running - if (Utilities.CheckIfRobloxRunning()) + if (Process.GetProcessesByName(App.RobloxAppName).Any()) { App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); @@ -1004,7 +1004,7 @@ private async Task ApplyModifications() if (File.Exists(fileVersionFolder)) { - if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) + if (Utility.MD5Hash.FromFile(fileModFolder) == Utility.MD5Hash.FromFile(fileVersionFolder)) continue; } @@ -1072,7 +1072,7 @@ private static async Task CheckModPreset(bool condition, string location, string await File.WriteAllBytesAsync(modFolderLocation, binaryData); } } - else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) + else if (File.Exists(modFolderLocation) && Utility.MD5Hash.FromFile(modFolderLocation) == Utility.MD5Hash.FromBytes(binaryData)) { File.Delete(modFolderLocation); } @@ -1091,7 +1091,8 @@ private async Task DownloadPackage(Package package) { FileInfo file = new(packageLocation); - string calculatedMD5 = Utilities.MD5File(packageLocation); + string calculatedMD5 = Utility.MD5Hash.FromFile(packageLocation); + if (calculatedMD5 != package.Signature) { App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/FastFlagManager.cs similarity index 98% rename from Bloxstrap/Singletons/FastFlagManager.cs rename to Bloxstrap/FastFlagManager.cs index f0ee4d01..104905e9 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/FastFlagManager.cs @@ -1,10 +1,8 @@ -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Text.Json; -namespace Bloxstrap.Singletons +namespace Bloxstrap { public class FastFlagManager : JsonManager> { @@ -103,18 +101,18 @@ public void SetValue(string key, object? value) // this will set the flag to the corresponding value if the condition is true // if the condition is not true, the flag will be erased - public void SetValueIf(bool condition, string key, object? value) - { + public void SetValueIf(bool condition, string key, object? value) + { if (condition) SetValue(key, value); else if (GetValue(key) is not null) - SetValue(key, null); + SetValue(key, null); } - public void SetValueOnce(string key, object? value) - { + public void SetValueOnce(string key, object? value) + { if (GetValue(key) is null) - SetValue(key, value); + SetValue(key, value); } // this returns null if the fflag doesn't exist diff --git a/Bloxstrap/Singletons/JsonManager.cs b/Bloxstrap/JsonManager.cs similarity index 98% rename from Bloxstrap/Singletons/JsonManager.cs rename to Bloxstrap/JsonManager.cs index 7f212e87..f888341a 100644 --- a/Bloxstrap/Singletons/JsonManager.cs +++ b/Bloxstrap/JsonManager.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text.Json; -namespace Bloxstrap.Singletons +namespace Bloxstrap { public class JsonManager where T : new() { diff --git a/Bloxstrap/Singletons/Logger.cs b/Bloxstrap/Logger.cs similarity index 98% rename from Bloxstrap/Singletons/Logger.cs rename to Bloxstrap/Logger.cs index 190f8b5d..ad4bc935 100644 --- a/Bloxstrap/Singletons/Logger.cs +++ b/Bloxstrap/Logger.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading; -namespace Bloxstrap.Singletons +namespace Bloxstrap { // https://stackoverflow.com/a/53873141/11852173 // TODO - this kind of sucks diff --git a/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs b/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs index dfcc15ec..af9b34ae 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs @@ -1,7 +1,9 @@ using System; using System.Windows; using System.Windows.Forms; + using Bloxstrap.Extensions; +using Bloxstrap.Utility; namespace Bloxstrap.UI.BootstrapperDialogs.WinForms { diff --git a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs index ce1e3018..afb4a8c0 100644 --- a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; -using Bloxstrap.Singletons; -using System.ComponentModel; - namespace Bloxstrap.UI.Menu.ViewModels { public class FastFlagsViewModel : INotifyPropertyChanged @@ -17,7 +14,7 @@ public class FastFlagsViewModel : INotifyPropertyChanged public ICommand OpenClientSettingsCommand => new RelayCommand(OpenClientSettings); - private void OpenClientSettings() => Utilities.OpenWebsite(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); + private void OpenClientSettings() => Utilities.ShellExecute(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); public int FramerateLimit { @@ -40,19 +37,19 @@ public string SelectedRenderingMode return "Automatic"; } - set - { - foreach (var mode in RenderingModes) - { - if (mode.Key != "Automatic") - App.FastFlags.SetValue(mode.Value, null); - } - - if (value == "Automatic") - return; - - App.FastFlags.SetValue(RenderingModes[value], "True"); - App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True"); + set + { + foreach (var mode in RenderingModes) + { + if (mode.Key != "Automatic") + App.FastFlags.SetValue(mode.Value, null); + } + + if (value == "Automatic") + return; + + App.FastFlags.SetValue(RenderingModes[value], "True"); + App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True"); } } diff --git a/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs index 0b292a52..689945dd 100644 --- a/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs @@ -14,7 +14,7 @@ private static void OpenWebpage(string? location) if (location is null) return; - Utilities.OpenWebsite(location); + Utilities.ShellExecute(location); } } } diff --git a/Bloxstrap/Updater.cs b/Bloxstrap/Updater.cs index 5a7e979b..d229f1c7 100644 --- a/Bloxstrap/Updater.cs +++ b/Bloxstrap/Updater.cs @@ -78,7 +78,7 @@ public static void CheckInstalledVersion() if (isAutoUpgrade) { - EventHandler ReleaseNotesLauncher = new((_, _) => Utilities.OpenWebsite($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")); + EventHandler ReleaseNotesLauncher = new((_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")); App.Notification.BalloonTipTitle = $"Bloxstrap has been upgraded to v{currentVersionInfo.ProductVersion}"; App.Notification.BalloonTipText = "Click here to see what's new in this version"; diff --git a/Bloxstrap/Utilities.cs b/Bloxstrap/Utilities.cs index 5cce944b..53571d90 100644 --- a/Bloxstrap/Utilities.cs +++ b/Bloxstrap/Utilities.cs @@ -10,11 +10,6 @@ namespace Bloxstrap { static class Utilities { - public static bool IsDirectoryEmpty(string path) - { - return !Directory.EnumerateFileSystemEntries(path).Any(); - } - public static long GetFreeDiskSpace(string path) { foreach (DriveInfo drive in DriveInfo.GetDrives()) @@ -26,24 +21,7 @@ public static long GetFreeDiskSpace(string path) return -1; } - public static int GetProcessCount(string processName, bool log = true) - { - if (log) - App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Checking if '{processName}' is running..."); - - Process[] processes = Process.GetProcessesByName(processName); - - if (log) - App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Found {processes.Length} process(es) running for '{processName}'"); - - return processes.Length; - } - - public static bool CheckIfProcessRunning(string processName, bool log = true) => GetProcessCount(processName, log) >= 1; - - public static bool CheckIfRobloxRunning(bool log = true) => CheckIfProcessRunning("RobloxPlayerBeta", log); - - public static void OpenWebsite(string website) => Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true }); + public static void ShellExecute(string website) => Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true }); public static async Task GetJson(string url) { @@ -61,41 +39,5 @@ public static int GetProcessCount(string processName, bool log = true) return default; } } - - public static string MD5File(string filename) - { - using (MD5 md5 = MD5.Create()) - { - using (FileStream stream = File.OpenRead(filename)) - { - byte[] hash = md5.ComputeHash(stream); - return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - } - } - } - - public static string MD5Data(byte[] data) - { - using (MD5 md5 = MD5.Create()) - { - byte[] hash = md5.ComputeHash(data); - return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - } - } - - // quick and hacky way of getting a value from any key/value pair formatted list - // (command line args, uri params, etc) - public static string? GetKeyValue(string subject, string key, char delimiter) - { - if (subject.LastIndexOf(key) == -1) - return null; - - string substr = subject.Substring(subject.LastIndexOf(key) + key.Length); - - if (!substr.Contains(delimiter)) - return null; - - return substr.Split(delimiter)[0]; - } } } diff --git a/Bloxstrap/Tools/AsyncMutex.cs b/Bloxstrap/Utility/AsyncMutex.cs similarity index 97% rename from Bloxstrap/Tools/AsyncMutex.cs rename to Bloxstrap/Utility/AsyncMutex.cs index fa6d1377..e6e972f9 100644 --- a/Bloxstrap/Tools/AsyncMutex.cs +++ b/Bloxstrap/Utility/AsyncMutex.cs @@ -1,102 +1,102 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap.Tools -{ - // https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e - - public sealed class AsyncMutex : IAsyncDisposable - { - private readonly string _name; - private Task? _mutexTask; - private ManualResetEventSlim? _releaseEvent; - private CancellationTokenSource? _cancellationTokenSource; - - public AsyncMutex(string name) - { - _name = name; - } - - public Task AcquireAsync(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - TaskCompletionSource taskCompletionSource = new(); - - _releaseEvent = new ManualResetEventSlim(); - _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - - // Putting all mutex manipulation in its own task as it doesn't work in async contexts - // Note: this task should not throw. - _mutexTask = Task.Factory.StartNew( - state => - { - try - { - CancellationToken cancellationToken = _cancellationTokenSource.Token; - using var mutex = new Mutex(false, _name); - try - { - // Wait for either the mutex to be acquired, or cancellation - if (WaitHandle.WaitAny(new[] { mutex, cancellationToken.WaitHandle }) != 0) - { - taskCompletionSource.SetCanceled(cancellationToken); - return; - } - } - catch (AbandonedMutexException) - { - // Abandoned by another process, we acquired it. - } - - taskCompletionSource.SetResult(); - - // Wait until the release call - _releaseEvent.Wait(); - - mutex.ReleaseMutex(); - } - catch (OperationCanceledException) - { - taskCompletionSource.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - taskCompletionSource.TrySetException(ex); - } - }, - state: null, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); - - return taskCompletionSource.Task; - } - - public async Task ReleaseAsync() - { - _releaseEvent?.Set(); - - if (_mutexTask != null) - { - await _mutexTask; - } - } - - public async ValueTask DisposeAsync() - { - // Ensure the mutex task stops waiting for any acquire - _cancellationTokenSource?.Cancel(); - - // Ensure the mutex is released - await ReleaseAsync(); - - _releaseEvent?.Dispose(); - _cancellationTokenSource?.Dispose(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Bloxstrap.Tools +{ + // https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e + + public sealed class AsyncMutex : IAsyncDisposable + { + private readonly string _name; + private Task? _mutexTask; + private ManualResetEventSlim? _releaseEvent; + private CancellationTokenSource? _cancellationTokenSource; + + public AsyncMutex(string name) + { + _name = name; + } + + public Task AcquireAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + TaskCompletionSource taskCompletionSource = new(); + + _releaseEvent = new ManualResetEventSlim(); + _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + + // Putting all mutex manipulation in its own task as it doesn't work in async contexts + // Note: this task should not throw. + _mutexTask = Task.Factory.StartNew( + state => + { + try + { + CancellationToken cancellationToken = _cancellationTokenSource.Token; + using var mutex = new Mutex(false, _name); + try + { + // Wait for either the mutex to be acquired, or cancellation + if (WaitHandle.WaitAny(new[] { mutex, cancellationToken.WaitHandle }) != 0) + { + taskCompletionSource.SetCanceled(cancellationToken); + return; + } + } + catch (AbandonedMutexException) + { + // Abandoned by another process, we acquired it. + } + + taskCompletionSource.SetResult(); + + // Wait until the release call + _releaseEvent.Wait(); + + mutex.ReleaseMutex(); + } + catch (OperationCanceledException) + { + taskCompletionSource.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + taskCompletionSource.TrySetException(ex); + } + }, + state: null, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return taskCompletionSource.Task; + } + + public async Task ReleaseAsync() + { + _releaseEvent?.Set(); + + if (_mutexTask != null) + { + await _mutexTask; + } + } + + public async ValueTask DisposeAsync() + { + // Ensure the mutex task stops waiting for any acquire + _cancellationTokenSource?.Cancel(); + + // Ensure the mutex is released + await ReleaseAsync(); + + _releaseEvent?.Dispose(); + _cancellationTokenSource?.Dispose(); + } + } +} diff --git a/Bloxstrap/Utility/MD5Hash.cs b/Bloxstrap/Utility/MD5Hash.cs new file mode 100644 index 00000000..9e1abcb9 --- /dev/null +++ b/Bloxstrap/Utility/MD5Hash.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.Utility +{ + public static class MD5Hash + { + public static string FromFile(string filename) + { + using (MD5 md5 = MD5.Create()) + { + using (FileStream stream = File.OpenRead(filename)) + { + byte[] hash = md5.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } + + public static string FromBytes(byte[] data) + { + using (MD5 md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(data); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } +} diff --git a/Bloxstrap/NativeMethods.cs b/Bloxstrap/Utility/NativeMethods.cs similarity index 91% rename from Bloxstrap/NativeMethods.cs rename to Bloxstrap/Utility/NativeMethods.cs index 7cf69810..f27c0e1a 100644 --- a/Bloxstrap/NativeMethods.cs +++ b/Bloxstrap/Utility/NativeMethods.cs @@ -4,8 +4,8 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; - -namespace Bloxstrap + +namespace Bloxstrap.Utility { static class NativeMethods { diff --git a/Bloxstrap/Tools/SystemEvent.cs b/Bloxstrap/Utility/SystemEvent.cs similarity index 96% rename from Bloxstrap/Tools/SystemEvent.cs rename to Bloxstrap/Utility/SystemEvent.cs index 098dc63c..05eb590c 100644 --- a/Bloxstrap/Tools/SystemEvent.cs +++ b/Bloxstrap/Utility/SystemEvent.cs @@ -1,47 +1,47 @@ -/* - * Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs) - * MIT License - * Copyright (c) 2015-present MaximumADHD -*/ - -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap.Tools -{ - public class SystemEvent : EventWaitHandle - { - public string Name { get; private set; } - - public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name) - { - if (init) - Reset(); - else - Set(); - - Name = name; - } - - public override string ToString() - { - return Name; - } - - public Task WaitForEvent() - { - return Task.Run(WaitOne); - } - - public Task WaitForEvent(TimeSpan timeout, bool exitContext = false) - { - return Task.Run(() => WaitOne(timeout, exitContext)); - } - - public Task WaitForEvent(int millisecondsTimeout, bool exitContext = false) - { - return Task.Run(() => WaitOne(millisecondsTimeout, exitContext)); - } - } -} +/* + * Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs) + * MIT License + * Copyright (c) 2015-present MaximumADHD +*/ + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Bloxstrap.Tools +{ + public class SystemEvent : EventWaitHandle + { + public string Name { get; private set; } + + public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name) + { + if (init) + Reset(); + else + Set(); + + Name = name; + } + + public override string ToString() + { + return Name; + } + + public Task WaitForEvent() + { + return Task.Run(WaitOne); + } + + public Task WaitForEvent(TimeSpan timeout, bool exitContext = false) + { + return Task.Run(() => WaitOne(timeout, exitContext)); + } + + public Task WaitForEvent(int millisecondsTimeout, bool exitContext = false) + { + return Task.Run(() => WaitOne(millisecondsTimeout, exitContext)); + } + } +} diff --git a/Bloxstrap/WindowScaling.cs b/Bloxstrap/Utility/WindowScaling.cs similarity index 78% rename from Bloxstrap/WindowScaling.cs rename to Bloxstrap/Utility/WindowScaling.cs index 3908587e..c75139e0 100644 --- a/Bloxstrap/WindowScaling.cs +++ b/Bloxstrap/Utility/WindowScaling.cs @@ -1,34 +1,31 @@ -using System; -using System.Windows; -using System.Windows.Forms; - -namespace Bloxstrap -{ - public static class WindowScaling - { - public static double GetFactor() - { - return Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; - } - - public static int GetScaledNumber(int number) - { - return (int)Math.Ceiling(number * GetFactor()); - } - - public static System.Drawing.Size GetScaledSize(System.Drawing.Size size) - { - return new System.Drawing.Size(GetScaledNumber(size.Width), GetScaledNumber(size.Height)); - } - - public static System.Drawing.Point GetScaledPoint(System.Drawing.Point point) - { - return new System.Drawing.Point(GetScaledNumber(point.X), GetScaledNumber(point.Y)); - } - - public static Padding GetScaledPadding(Padding padding) - { - return new Padding(GetScaledNumber(padding.Left), GetScaledNumber(padding.Top), GetScaledNumber(padding.Right), GetScaledNumber(padding.Bottom)); - } - } -} +using System; +using System.Windows; +using System.Windows.Forms; + +namespace Bloxstrap.Utility +{ + public static class WindowScaling + { + public static double ScaleFactor => Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; + + public static int GetScaledNumber(int number) + { + return (int)Math.Ceiling(number * ScaleFactor); + } + + public static System.Drawing.Size GetScaledSize(System.Drawing.Size size) + { + return new System.Drawing.Size(GetScaledNumber(size.Width), GetScaledNumber(size.Height)); + } + + public static System.Drawing.Point GetScaledPoint(System.Drawing.Point point) + { + return new System.Drawing.Point(GetScaledNumber(point.X), GetScaledNumber(point.Y)); + } + + public static Padding GetScaledPadding(Padding padding) + { + return new Padding(GetScaledNumber(padding.Left), GetScaledNumber(padding.Top), GetScaledNumber(padding.Right), GetScaledNumber(padding.Bottom)); + } + } +} From 6af7188ffefd894f350b04fa28b635ea3c5987e6 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 22:57:09 +0100 Subject: [PATCH 064/178] Add notice for missing Windows Media components --- Bloxstrap/Bootstrapper.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 66cfddc0..5c0c9df4 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -261,6 +261,14 @@ private async Task StartRoblox() return; } + if (!File.Exists("C:\\Windows\\System32\\mfplat.dll")) + { + App.ShowMessageBox("Roblox requires the use of Windows Media Foundation components. You appear to be missing them, likely because you are using an N edition of Windows. Please install them first, and then launch Roblox.", MessageBoxImage.Error); + Utilities.ShellExecute("https://support.microsoft.com/en-us/topic/media-feature-pack-list-for-windows-n-editions-c1c6fffa-d052-8338-7a79-a4bb980a700a"); + Dialog?.CloseBootstrapper(); + return; + } + _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) From 17c36ccb91a90d45af27f8269f63d87447f113bb Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 23:10:39 +0100 Subject: [PATCH 065/178] Line ending normalization... again... --- Bloxstrap/App.xaml.cs | 710 +++++------ Bloxstrap/Bootstrapper.cs | 2454 ++++++++++++++++++------------------- 2 files changed, 1582 insertions(+), 1582 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index affaefaf..d2c1cd0e 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -1,357 +1,357 @@ -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Net; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Threading; - -using Microsoft.Win32; - -using Bloxstrap.Extensions; -using Bloxstrap.Models; -using Bloxstrap.UI.BootstrapperDialogs; -using Bloxstrap.UI.Menu.Views; +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; + +using Microsoft.Win32; + +using Bloxstrap.Extensions; +using Bloxstrap.Models; +using Bloxstrap.UI.BootstrapperDialogs; +using Bloxstrap.UI.Menu.Views; using Bloxstrap.Utility; -namespace Bloxstrap -{ - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { - public static readonly CultureInfo CultureFormat = CultureInfo.InvariantCulture; - - public const string ProjectName = "Bloxstrap"; - public const string ProjectRepository = "pizzaboxer/bloxstrap"; - public const string RobloxAppName = "RobloxPlayerBeta"; - - // used only for communicating between app and menu - use Directories.Base for anything else - public static string BaseDirectory = null!; - public static bool ShouldSaveConfigs { get; set; } = false; - public static bool IsSetupComplete { get; set; } = true; - public static bool IsFirstRun { get; private set; } = true; - public static bool IsQuiet { get; private set; } = false; - public static bool IsUninstall { get; private set; } = false; - public static bool IsNoLaunch { get; private set; } = false; - public static bool IsUpgrade { get; private set; } = false; - public static bool IsMenuLaunch { get; private set; } = false; - public static string[] LaunchArgs { get; private set; } = null!; - - public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; - - // singletons - public static readonly Logger Logger = new(); - public static readonly JsonManager Settings = new(); - public static readonly JsonManager State = new(); - public static readonly FastFlagManager FastFlags = new(); - public static readonly HttpClient HttpClient = new(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }); - - public static System.Windows.Forms.NotifyIcon Notification { get; private set; } = null!; - - // shorthand - public static MessageBoxResult ShowMessageBox(string message, MessageBoxImage icon = MessageBoxImage.None, MessageBoxButton buttons = MessageBoxButton.OK) - { - if (IsQuiet) - return MessageBoxResult.None; - - return MessageBox.Show(message, ProjectName, buttons, icon); - } - - public static void Terminate(int code = Bootstrapper.ERROR_SUCCESS) - { - Logger.WriteLine($"[App::Terminate] Terminating with exit code {code}"); - Settings.Save(); - State.Save(); - Notification.Dispose(); - Environment.Exit(code); - } - - private void InitLog() - { - // if we're running for the first time or uninstalling, log to temp folder - // else, log to bloxstrap folder - - bool isUsingTempDir = IsFirstRun || IsUninstall; - string logdir = isUsingTempDir ? Path.Combine(Directories.LocalAppData, "Temp") : Path.Combine(Directories.Base, "Logs"); - string timestamp = DateTime.UtcNow.ToString("yyyyMMdd'T'HHmmss'Z'"); - int processId = Process.GetCurrentProcess().Id; - - Logger.Initialize(Path.Combine(logdir, $"{ProjectName}_{timestamp}_{processId}.log")); - - // clean up any logs older than a week - if (!isUsingTempDir) - { - foreach (FileInfo log in new DirectoryInfo(logdir).GetFiles()) - { - if (log.LastWriteTimeUtc.AddDays(7) > DateTime.UtcNow) - continue; - - Logger.WriteLine($"[App::InitLog] Cleaning up old log file '{log.Name}'"); - log.Delete(); - } - } - } - - void GlobalExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs e) - { - e.Handled = true; - - Logger.WriteLine("[App::OnStartup] An exception occurred when running the main thread"); - Logger.WriteLine($"[App::OnStartup] {e.Exception}"); - - if (!IsQuiet) - Settings.Prop.BootstrapperStyle.GetNew().ShowError($"{e.Exception.GetType()}: {e.Exception.Message}"); - - Terminate(Bootstrapper.ERROR_INSTALL_FAILURE); - } - - protected override void OnStartup(StartupEventArgs e) - { - base.OnStartup(e); - - Logger.WriteLine($"[App::OnStartup] Starting {ProjectName} v{Version}"); - - // To customize application configuration such as set high DPI settings or default font, - // see https://aka.ms/applicationconfiguration. - ApplicationConfiguration.Initialize(); - - LaunchArgs = e.Args; - - HttpClient.Timeout = TimeSpan.FromMinutes(5); - HttpClient.DefaultRequestHeaders.Add("User-Agent", ProjectRepository); - - if (LaunchArgs.Length > 0) - { - if (Array.IndexOf(LaunchArgs, "-preferences") != -1 || Array.IndexOf(LaunchArgs, "-menu") != -1) - { - Logger.WriteLine("[App::OnStartup] Started with IsMenuLaunch flag"); - IsMenuLaunch = true; - } - - if (Array.IndexOf(LaunchArgs, "-quiet") != -1) - { - Logger.WriteLine("[App::OnStartup] Started with IsQuiet flag"); - IsQuiet = true; - } - - if (Array.IndexOf(LaunchArgs, "-uninstall") != -1) - { - Logger.WriteLine("[App::OnStartup] Started with IsUninstall flag"); - IsUninstall = true; - } - - if (Array.IndexOf(LaunchArgs, "-nolaunch") != -1) - { - Logger.WriteLine("[App::OnStartup] Started with IsNoLaunch flag"); - IsNoLaunch = true; - } - - if (Array.IndexOf(LaunchArgs, "-upgrade") != -1) - { - Logger.WriteLine("[App::OnStartup] Bloxstrap started with IsUpgrade flag"); - IsUpgrade = true; - } - } - - // so this needs to be here because winforms moment - // onclick events will not fire unless this is defined here in the main thread so uhhhhh - // we'll show the icon if we're launching roblox since we're likely gonna be showing a - // bunch of notifications, and always showing it just makes the most sense i guess since it - // indicates that bloxstrap is running, even in the background - Notification = new() - { - Icon = Bloxstrap.Properties.Resources.IconBloxstrap, - Text = ProjectName, - Visible = !IsMenuLaunch - }; - - // check if installed - using (RegistryKey? registryKey = Registry.CurrentUser.OpenSubKey($@"Software\{ProjectName}")) - { - string? installLocation = null; - - if (registryKey is not null) - installLocation = (string?)registryKey.GetValue("InstallLocation"); - - if (registryKey is null || installLocation is null) - { - Logger.WriteLine("[App::OnStartup] Running first-time install"); - - BaseDirectory = Path.Combine(Directories.LocalAppData, ProjectName); - InitLog(); - - if (!IsQuiet) - { - IsSetupComplete = false; - FastFlags.Load(); - new MainWindow().ShowDialog(); - } - } - else - { - IsFirstRun = false; - BaseDirectory = installLocation; - } - } - - // exit if we don't click the install button on installation - if (!IsSetupComplete) - { - Logger.WriteLine("[App::OnStartup] Installation cancelled!"); - Environment.Exit(Bootstrapper.ERROR_INSTALL_USEREXIT); - } - - Directories.Initialize(BaseDirectory); - - // we shouldn't save settings on the first run until the first installation is finished, - // just in case the user decides to cancel the install - if (!IsFirstRun) - { - InitLog(); - Settings.Load(); - State.Load(); - FastFlags.Load(); - } - -#if !DEBUG - if (!IsUninstall && !IsFirstRun) - Updater.CheckInstalledVersion(); -#endif - - string commandLine = ""; - - if (IsMenuLaunch) - { - Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault(); - - if (menuProcess is not null) - { - IntPtr handle = menuProcess.MainWindowHandle; - Logger.WriteLine($"[App::OnStartup] Found an already existing menu window with handle {handle}"); - NativeMethods.SetForegroundWindow(handle); - } - else - { - if (Process.GetProcessesByName(ProjectName).Length > 1) - ShowMessageBox($"{ProjectName} is currently running, likely as a background Roblox process. Please note that not all your changes will immediately apply until you close all currently open Roblox instances.", MessageBoxImage.Information); - - new MainWindow().ShowDialog(); - } - } - else if (LaunchArgs.Length > 0) - { - if (LaunchArgs[0].StartsWith("roblox-player:")) - { - commandLine = ProtocolHandler.ParseUri(LaunchArgs[0]); - } - else if (LaunchArgs[0].StartsWith("roblox:")) - { - if (Settings.Prop.UseDisableAppPatch) - ShowMessageBox("Roblox was launched via a deeplink, however the desktop app is required for deeplink launching to work. Because you've opted to disable the desktop app, it will temporarily be re-enabled for this launch only.", MessageBoxImage.Information); - - commandLine = $"--app --deeplink {LaunchArgs[0]}"; - } - else - { - commandLine = "--app"; - } - } - else - { - commandLine = "--app"; - } - - if (!String.IsNullOrEmpty(commandLine)) - { - if (!IsFirstRun) - ShouldSaveConfigs = true; - - // start bootstrapper and show the bootstrapper modal if we're not running silently - Logger.WriteLine($"[App::OnStartup] Initializing bootstrapper"); - Bootstrapper bootstrapper = new(commandLine); - IBootstrapperDialog? dialog = null; - - if (!IsQuiet) - { - Logger.WriteLine($"[App::OnStartup] Initializing bootstrapper dialog"); - dialog = Settings.Prop.BootstrapperStyle.GetNew(); - bootstrapper.Dialog = dialog; - dialog.Bootstrapper = bootstrapper; - } - - // handle roblox singleton mutex for multi-instance launching - // note we're handling it here in the main thread and NOT in the - // bootstrapper as handling mutexes in async contexts suuuuuucks - - Mutex? singletonMutex = null; - - if (Settings.Prop.MultiInstanceLaunching) - { - Logger.WriteLine("[App::OnStartup] Creating singleton mutex"); - - try - { - Mutex.OpenExisting("ROBLOX_singletonMutex"); - Logger.WriteLine("[App::OnStartup] Warning - singleton mutex already exists!"); - } - catch - { - // create the singleton mutex before the game client does - singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); - } - } - - // there's a bug here that i have yet to fix! - // sometimes the task just terminates when the bootstrapper hasn't - // actually finished, causing the bootstrapper to hang indefinitely - // i have no idea how the fuck this happens, but it happens like VERY - // rarely so i'm not too concerned by it - // maybe one day ill find out why it happens - Task bootstrapperTask = Task.Run(() => bootstrapper.Run()).ContinueWith(t => - { - Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished"); - - if (t.IsFaulted) - Logger.WriteLine("[App::OnStartup] An exception occurred when running the bootstrapper"); - - if (t.Exception is null) - return; - - Logger.WriteLine($"[App::OnStartup] {t.Exception}"); - -#if DEBUG - throw t.Exception; -#else - var exception = t.Exception.InnerExceptions.Count >= 1 ? t.Exception.InnerExceptions[0] : t.Exception; - dialog?.ShowError($"{exception.GetType()}: {exception.Message}"); - Terminate(Bootstrapper.ERROR_INSTALL_FAILURE); -#endif - }); - - dialog?.ShowBootstrapper(); - bootstrapperTask.Wait(); - - if (singletonMutex is not null) - { - Logger.WriteLine($"[App::OnStartup] We have singleton mutex ownership! Running in background until all Roblox processes are closed"); - - // we've got ownership of the roblox singleton mutex! - // if we stop running, everything will screw up once any more roblox instances launched - while (Process.GetProcessesByName("RobloxPlayerBeta").Any()) - Thread.Sleep(5000); - } - } - - Logger.WriteLine($"[App::OnStartup] Successfully reached end of main thread. Terminating..."); - - Terminate(); - } - } -} +namespace Bloxstrap +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + public static readonly CultureInfo CultureFormat = CultureInfo.InvariantCulture; + + public const string ProjectName = "Bloxstrap"; + public const string ProjectRepository = "pizzaboxer/bloxstrap"; + public const string RobloxAppName = "RobloxPlayerBeta"; + + // used only for communicating between app and menu - use Directories.Base for anything else + public static string BaseDirectory = null!; + public static bool ShouldSaveConfigs { get; set; } = false; + public static bool IsSetupComplete { get; set; } = true; + public static bool IsFirstRun { get; private set; } = true; + public static bool IsQuiet { get; private set; } = false; + public static bool IsUninstall { get; private set; } = false; + public static bool IsNoLaunch { get; private set; } = false; + public static bool IsUpgrade { get; private set; } = false; + public static bool IsMenuLaunch { get; private set; } = false; + public static string[] LaunchArgs { get; private set; } = null!; + + public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; + + // singletons + public static readonly Logger Logger = new(); + public static readonly JsonManager Settings = new(); + public static readonly JsonManager State = new(); + public static readonly FastFlagManager FastFlags = new(); + public static readonly HttpClient HttpClient = new(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }); + + public static System.Windows.Forms.NotifyIcon Notification { get; private set; } = null!; + + // shorthand + public static MessageBoxResult ShowMessageBox(string message, MessageBoxImage icon = MessageBoxImage.None, MessageBoxButton buttons = MessageBoxButton.OK) + { + if (IsQuiet) + return MessageBoxResult.None; + + return MessageBox.Show(message, ProjectName, buttons, icon); + } + + public static void Terminate(int code = Bootstrapper.ERROR_SUCCESS) + { + Logger.WriteLine($"[App::Terminate] Terminating with exit code {code}"); + Settings.Save(); + State.Save(); + Notification.Dispose(); + Environment.Exit(code); + } + + private void InitLog() + { + // if we're running for the first time or uninstalling, log to temp folder + // else, log to bloxstrap folder + + bool isUsingTempDir = IsFirstRun || IsUninstall; + string logdir = isUsingTempDir ? Path.Combine(Directories.LocalAppData, "Temp") : Path.Combine(Directories.Base, "Logs"); + string timestamp = DateTime.UtcNow.ToString("yyyyMMdd'T'HHmmss'Z'"); + int processId = Process.GetCurrentProcess().Id; + + Logger.Initialize(Path.Combine(logdir, $"{ProjectName}_{timestamp}_{processId}.log")); + + // clean up any logs older than a week + if (!isUsingTempDir) + { + foreach (FileInfo log in new DirectoryInfo(logdir).GetFiles()) + { + if (log.LastWriteTimeUtc.AddDays(7) > DateTime.UtcNow) + continue; + + Logger.WriteLine($"[App::InitLog] Cleaning up old log file '{log.Name}'"); + log.Delete(); + } + } + } + + void GlobalExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs e) + { + e.Handled = true; + + Logger.WriteLine("[App::OnStartup] An exception occurred when running the main thread"); + Logger.WriteLine($"[App::OnStartup] {e.Exception}"); + + if (!IsQuiet) + Settings.Prop.BootstrapperStyle.GetNew().ShowError($"{e.Exception.GetType()}: {e.Exception.Message}"); + + Terminate(Bootstrapper.ERROR_INSTALL_FAILURE); + } + + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + Logger.WriteLine($"[App::OnStartup] Starting {ProjectName} v{Version}"); + + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + + LaunchArgs = e.Args; + + HttpClient.Timeout = TimeSpan.FromMinutes(5); + HttpClient.DefaultRequestHeaders.Add("User-Agent", ProjectRepository); + + if (LaunchArgs.Length > 0) + { + if (Array.IndexOf(LaunchArgs, "-preferences") != -1 || Array.IndexOf(LaunchArgs, "-menu") != -1) + { + Logger.WriteLine("[App::OnStartup] Started with IsMenuLaunch flag"); + IsMenuLaunch = true; + } + + if (Array.IndexOf(LaunchArgs, "-quiet") != -1) + { + Logger.WriteLine("[App::OnStartup] Started with IsQuiet flag"); + IsQuiet = true; + } + + if (Array.IndexOf(LaunchArgs, "-uninstall") != -1) + { + Logger.WriteLine("[App::OnStartup] Started with IsUninstall flag"); + IsUninstall = true; + } + + if (Array.IndexOf(LaunchArgs, "-nolaunch") != -1) + { + Logger.WriteLine("[App::OnStartup] Started with IsNoLaunch flag"); + IsNoLaunch = true; + } + + if (Array.IndexOf(LaunchArgs, "-upgrade") != -1) + { + Logger.WriteLine("[App::OnStartup] Bloxstrap started with IsUpgrade flag"); + IsUpgrade = true; + } + } + + // so this needs to be here because winforms moment + // onclick events will not fire unless this is defined here in the main thread so uhhhhh + // we'll show the icon if we're launching roblox since we're likely gonna be showing a + // bunch of notifications, and always showing it just makes the most sense i guess since it + // indicates that bloxstrap is running, even in the background + Notification = new() + { + Icon = Bloxstrap.Properties.Resources.IconBloxstrap, + Text = ProjectName, + Visible = !IsMenuLaunch + }; + + // check if installed + using (RegistryKey? registryKey = Registry.CurrentUser.OpenSubKey($@"Software\{ProjectName}")) + { + string? installLocation = null; + + if (registryKey is not null) + installLocation = (string?)registryKey.GetValue("InstallLocation"); + + if (registryKey is null || installLocation is null) + { + Logger.WriteLine("[App::OnStartup] Running first-time install"); + + BaseDirectory = Path.Combine(Directories.LocalAppData, ProjectName); + InitLog(); + + if (!IsQuiet) + { + IsSetupComplete = false; + FastFlags.Load(); + new MainWindow().ShowDialog(); + } + } + else + { + IsFirstRun = false; + BaseDirectory = installLocation; + } + } + + // exit if we don't click the install button on installation + if (!IsSetupComplete) + { + Logger.WriteLine("[App::OnStartup] Installation cancelled!"); + Environment.Exit(Bootstrapper.ERROR_INSTALL_USEREXIT); + } + + Directories.Initialize(BaseDirectory); + + // we shouldn't save settings on the first run until the first installation is finished, + // just in case the user decides to cancel the install + if (!IsFirstRun) + { + InitLog(); + Settings.Load(); + State.Load(); + FastFlags.Load(); + } + +#if !DEBUG + if (!IsUninstall && !IsFirstRun) + Updater.CheckInstalledVersion(); +#endif + + string commandLine = ""; + + if (IsMenuLaunch) + { + Process? menuProcess = Process.GetProcesses().Where(x => x.MainWindowTitle == $"{ProjectName} Menu").FirstOrDefault(); + + if (menuProcess is not null) + { + IntPtr handle = menuProcess.MainWindowHandle; + Logger.WriteLine($"[App::OnStartup] Found an already existing menu window with handle {handle}"); + NativeMethods.SetForegroundWindow(handle); + } + else + { + if (Process.GetProcessesByName(ProjectName).Length > 1) + ShowMessageBox($"{ProjectName} is currently running, likely as a background Roblox process. Please note that not all your changes will immediately apply until you close all currently open Roblox instances.", MessageBoxImage.Information); + + new MainWindow().ShowDialog(); + } + } + else if (LaunchArgs.Length > 0) + { + if (LaunchArgs[0].StartsWith("roblox-player:")) + { + commandLine = ProtocolHandler.ParseUri(LaunchArgs[0]); + } + else if (LaunchArgs[0].StartsWith("roblox:")) + { + if (Settings.Prop.UseDisableAppPatch) + ShowMessageBox("Roblox was launched via a deeplink, however the desktop app is required for deeplink launching to work. Because you've opted to disable the desktop app, it will temporarily be re-enabled for this launch only.", MessageBoxImage.Information); + + commandLine = $"--app --deeplink {LaunchArgs[0]}"; + } + else + { + commandLine = "--app"; + } + } + else + { + commandLine = "--app"; + } + + if (!String.IsNullOrEmpty(commandLine)) + { + if (!IsFirstRun) + ShouldSaveConfigs = true; + + // start bootstrapper and show the bootstrapper modal if we're not running silently + Logger.WriteLine($"[App::OnStartup] Initializing bootstrapper"); + Bootstrapper bootstrapper = new(commandLine); + IBootstrapperDialog? dialog = null; + + if (!IsQuiet) + { + Logger.WriteLine($"[App::OnStartup] Initializing bootstrapper dialog"); + dialog = Settings.Prop.BootstrapperStyle.GetNew(); + bootstrapper.Dialog = dialog; + dialog.Bootstrapper = bootstrapper; + } + + // handle roblox singleton mutex for multi-instance launching + // note we're handling it here in the main thread and NOT in the + // bootstrapper as handling mutexes in async contexts suuuuuucks + + Mutex? singletonMutex = null; + + if (Settings.Prop.MultiInstanceLaunching) + { + Logger.WriteLine("[App::OnStartup] Creating singleton mutex"); + + try + { + Mutex.OpenExisting("ROBLOX_singletonMutex"); + Logger.WriteLine("[App::OnStartup] Warning - singleton mutex already exists!"); + } + catch + { + // create the singleton mutex before the game client does + singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); + } + } + + // there's a bug here that i have yet to fix! + // sometimes the task just terminates when the bootstrapper hasn't + // actually finished, causing the bootstrapper to hang indefinitely + // i have no idea how the fuck this happens, but it happens like VERY + // rarely so i'm not too concerned by it + // maybe one day ill find out why it happens + Task bootstrapperTask = Task.Run(() => bootstrapper.Run()).ContinueWith(t => + { + Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished"); + + if (t.IsFaulted) + Logger.WriteLine("[App::OnStartup] An exception occurred when running the bootstrapper"); + + if (t.Exception is null) + return; + + Logger.WriteLine($"[App::OnStartup] {t.Exception}"); + +#if DEBUG + throw t.Exception; +#else + var exception = t.Exception.InnerExceptions.Count >= 1 ? t.Exception.InnerExceptions[0] : t.Exception; + dialog?.ShowError($"{exception.GetType()}: {exception.Message}"); + Terminate(Bootstrapper.ERROR_INSTALL_FAILURE); +#endif + }); + + dialog?.ShowBootstrapper(); + bootstrapperTask.Wait(); + + if (singletonMutex is not null) + { + Logger.WriteLine($"[App::OnStartup] We have singleton mutex ownership! Running in background until all Roblox processes are closed"); + + // we've got ownership of the roblox singleton mutex! + // if we stop running, everything will screw up once any more roblox instances launched + while (Process.GetProcessesByName("RobloxPlayerBeta").Any()) + Thread.Sleep(5000); + } + } + + Logger.WriteLine($"[App::OnStartup] Successfully reached end of main thread. Terminating..."); + + Terminate(); + } + } +} diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 5c0c9df4..5c17080c 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1,1233 +1,1233 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using System.Windows; - -using Microsoft.Win32; - -using Bloxstrap.Enums; -using Bloxstrap.Extensions; -using Bloxstrap.Integrations; -using Bloxstrap.Models; -using Bloxstrap.Tools; -using Bloxstrap.UI.BootstrapperDialogs; - -namespace Bloxstrap -{ - public class Bootstrapper - { - #region Properties - - // https://learn.microsoft.com/en-us/windows/win32/msi/error-codes - public const int ERROR_SUCCESS = 0; - public const int ERROR_INSTALL_USEREXIT = 1602; - public const int ERROR_INSTALL_FAILURE = 1603; - - // in case a new package is added, you can find the corresponding directory - // by opening the stock bootstrapper in a hex editor - // TODO - there ideally should be a less static way to do this that's not hardcoded? - private static readonly IReadOnlyDictionary PackageDirectories = new Dictionary() - { - { "RobloxApp.zip", @"" }, - { "shaders.zip", @"shaders\" }, - { "ssl.zip", @"ssl\" }, - - // the runtime installer is only extracted if it needs installing - { "WebView2.zip", @"" }, - { "WebView2RuntimeInstaller.zip", @"WebView2RuntimeInstaller\" }, - - { "content-avatar.zip", @"content\avatar\" }, - { "content-configs.zip", @"content\configs\" }, - { "content-fonts.zip", @"content\fonts\" }, - { "content-sky.zip", @"content\sky\" }, - { "content-sounds.zip", @"content\sounds\" }, - { "content-textures2.zip", @"content\textures\" }, - { "content-models.zip", @"content\models\" }, - - { "content-textures3.zip", @"PlatformContent\pc\textures\" }, - { "content-terrain.zip", @"PlatformContent\pc\terrain\" }, - { "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" }, - - { "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" }, - { "extracontent-translations.zip", @"ExtraContent\translations\" }, - { "extracontent-models.zip", @"ExtraContent\models\" }, - { "extracontent-textures.zip", @"ExtraContent\textures\" }, - { "extracontent-places.zip", @"ExtraContent\places\" }, - }; - - private const string AppSettings = - "\r\n" + - "\r\n" + - " content\r\n" + - " http://www.roblox.com\r\n" + - "\r\n"; - - private readonly CancellationTokenSource _cancelTokenSource = new(); - - private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); - private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); - - private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); - - private string _launchCommandLine; - - private string _latestVersionGuid = null!; - private PackageManifest _versionPackageManifest = null!; - private string _versionFolder = null!; - - private bool _isInstalling = false; - private double _progressIncrement; - private long _totalDownloadedBytes = 0; - private int _packagesExtracted = 0; - private bool _cancelFired = false; - - public IBootstrapperDialog? Dialog = null; - #endregion - - #region Core - public Bootstrapper(string launchCommandLine) - { - _launchCommandLine = launchCommandLine; - } - - private void SetStatus(string message) - { - App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); - - // yea idk - if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) - message = message.Replace("...", ""); - - if (Dialog is not null) - Dialog.Message = message; - } - - private void UpdateProgressbar() - { - int newProgress = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes); - - // bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100 - // too lazy to fix properly so lol - if (newProgress > 100) - return; - - if (Dialog is not null) - Dialog.ProgressValue = newProgress; - } - - public async Task Run() - { - App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); - - if (App.IsUninstall) - { - Uninstall(); - return; - } - -#if !DEBUG - if (!App.IsFirstRun && App.Settings.Prop.CheckForUpdates) - await CheckForUpdates(); -#endif - - // ensure only one instance of the bootstrapper is running at the time - // so that we don't have stuff like two updates happening simultaneously - - bool mutexExists = false; - - try - { - Mutex.OpenExisting("Bloxstrap_BootstrapperMutex").Close(); - App.Logger.WriteLine("[Bootstrapper::Run] Bloxstrap_BootstrapperMutex mutex exists, waiting..."); - mutexExists = true; - } - catch (Exception) - { - // no mutex exists - } - - // wait for mutex to be released if it's not yet - await using AsyncMutex mutex = new("Bloxstrap_BootstrapperMutex"); - await mutex.AcquireAsync(_cancelTokenSource.Token); - - // reload our configs since they've likely changed by now - if (mutexExists) - { - App.Settings.Load(); - App.State.Load(); - } - - await CheckLatestVersion(); - - CheckInstallMigration(); - - // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist - if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) - await InstallLatestVersion(); - - if (App.IsFirstRun) - App.ShouldSaveConfigs = true; - - MigrateIntegrations(); - - await InstallWebView2(); - - App.FastFlags.Save(); - await ApplyModifications(); - - if (App.IsFirstRun || FreshInstall) - { - Register(); - RegisterProgramSize(); - } - - CheckInstall(); - - // at this point we've finished updating our configs - App.Settings.Save(); - App.State.Save(); - App.ShouldSaveConfigs = false; - - await mutex.ReleaseAsync(); - - if (App.IsFirstRun && App.IsNoLaunch) - Dialog?.ShowSuccess($"{App.ProjectName} has successfully installed"); - else if (!App.IsNoLaunch && !_cancelFired) - await StartRoblox(); - } - - private async Task CheckLatestVersion() - { - SetStatus("Connecting to Roblox..."); - - ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); - - // briefly check if current channel is suitable to use - if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) - { - string? switchDefaultPrompt = null; - ClientVersion? defaultChannelInfo = null; - - App.Logger.WriteLine($"[Bootstrapper::CheckLatestVersion] Checking if current channel is suitable to use..."); - - if (String.IsNullOrEmpty(switchDefaultPrompt)) - { - // this SUCKS - defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); - int defaultChannelVersion = Int32.Parse(defaultChannelInfo.Version.Split('.')[1]); - int currentChannelVersion = Int32.Parse(clientVersion.Version.Split('.')[1]); - - if (currentChannelVersion < defaultChannelVersion) - switchDefaultPrompt = $"Your current preferred channel ({App.Settings.Prop.Channel}) appears to no longer be receiving updates. Would you like to switch to {RobloxDeployment.DefaultChannel}?"; - } - - if (!String.IsNullOrEmpty(switchDefaultPrompt)) - { - MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox(switchDefaultPrompt, MessageBoxImage.Question, MessageBoxButton.YesNo); - - if (result == MessageBoxResult.Yes) - { - App.Settings.Prop.Channel = RobloxDeployment.DefaultChannel; - App.Logger.WriteLine($"[DeployManager::SwitchToDefault] Changed Roblox release channel from {App.Settings.Prop.Channel} to {RobloxDeployment.DefaultChannel}"); - - if (defaultChannelInfo is null) - defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); - - clientVersion = defaultChannelInfo; - } - } - } - - _latestVersionGuid = clientVersion.VersionGuid; - _versionFolder = Path.Combine(Directories.Versions, _latestVersionGuid); - _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); - } - - private async Task StartRoblox() - { - SetStatus("Starting Roblox..."); - - if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) - { - Utilities.ShellExecute("https://www.roblox.com/games"); - Dialog?.CloseBootstrapper(); - return; - } - +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows; + +using Microsoft.Win32; + +using Bloxstrap.Enums; +using Bloxstrap.Extensions; +using Bloxstrap.Integrations; +using Bloxstrap.Models; +using Bloxstrap.Tools; +using Bloxstrap.UI.BootstrapperDialogs; + +namespace Bloxstrap +{ + public class Bootstrapper + { + #region Properties + + // https://learn.microsoft.com/en-us/windows/win32/msi/error-codes + public const int ERROR_SUCCESS = 0; + public const int ERROR_INSTALL_USEREXIT = 1602; + public const int ERROR_INSTALL_FAILURE = 1603; + + // in case a new package is added, you can find the corresponding directory + // by opening the stock bootstrapper in a hex editor + // TODO - there ideally should be a less static way to do this that's not hardcoded? + private static readonly IReadOnlyDictionary PackageDirectories = new Dictionary() + { + { "RobloxApp.zip", @"" }, + { "shaders.zip", @"shaders\" }, + { "ssl.zip", @"ssl\" }, + + // the runtime installer is only extracted if it needs installing + { "WebView2.zip", @"" }, + { "WebView2RuntimeInstaller.zip", @"WebView2RuntimeInstaller\" }, + + { "content-avatar.zip", @"content\avatar\" }, + { "content-configs.zip", @"content\configs\" }, + { "content-fonts.zip", @"content\fonts\" }, + { "content-sky.zip", @"content\sky\" }, + { "content-sounds.zip", @"content\sounds\" }, + { "content-textures2.zip", @"content\textures\" }, + { "content-models.zip", @"content\models\" }, + + { "content-textures3.zip", @"PlatformContent\pc\textures\" }, + { "content-terrain.zip", @"PlatformContent\pc\terrain\" }, + { "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" }, + + { "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" }, + { "extracontent-translations.zip", @"ExtraContent\translations\" }, + { "extracontent-models.zip", @"ExtraContent\models\" }, + { "extracontent-textures.zip", @"ExtraContent\textures\" }, + { "extracontent-places.zip", @"ExtraContent\places\" }, + }; + + private const string AppSettings = + "\r\n" + + "\r\n" + + " content\r\n" + + " http://www.roblox.com\r\n" + + "\r\n"; + + private readonly CancellationTokenSource _cancelTokenSource = new(); + + private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); + private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk"); + + private string _playerLocation => Path.Combine(_versionFolder, "RobloxPlayerBeta.exe"); + + private string _launchCommandLine; + + private string _latestVersionGuid = null!; + private PackageManifest _versionPackageManifest = null!; + private string _versionFolder = null!; + + private bool _isInstalling = false; + private double _progressIncrement; + private long _totalDownloadedBytes = 0; + private int _packagesExtracted = 0; + private bool _cancelFired = false; + + public IBootstrapperDialog? Dialog = null; + #endregion + + #region Core + public Bootstrapper(string launchCommandLine) + { + _launchCommandLine = launchCommandLine; + } + + private void SetStatus(string message) + { + App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); + + // yea idk + if (App.Settings.Prop.BootstrapperStyle == BootstrapperStyle.ByfronDialog) + message = message.Replace("...", ""); + + if (Dialog is not null) + Dialog.Message = message; + } + + private void UpdateProgressbar() + { + int newProgress = (int)Math.Floor(_progressIncrement * _totalDownloadedBytes); + + // bugcheck: if we're restoring a file from a package, it'll incorrectly increment the progress beyond 100 + // too lazy to fix properly so lol + if (newProgress > 100) + return; + + if (Dialog is not null) + Dialog.ProgressValue = newProgress; + } + + public async Task Run() + { + App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); + + if (App.IsUninstall) + { + Uninstall(); + return; + } + +#if !DEBUG + if (!App.IsFirstRun && App.Settings.Prop.CheckForUpdates) + await CheckForUpdates(); +#endif + + // ensure only one instance of the bootstrapper is running at the time + // so that we don't have stuff like two updates happening simultaneously + + bool mutexExists = false; + + try + { + Mutex.OpenExisting("Bloxstrap_BootstrapperMutex").Close(); + App.Logger.WriteLine("[Bootstrapper::Run] Bloxstrap_BootstrapperMutex mutex exists, waiting..."); + mutexExists = true; + } + catch (Exception) + { + // no mutex exists + } + + // wait for mutex to be released if it's not yet + await using AsyncMutex mutex = new("Bloxstrap_BootstrapperMutex"); + await mutex.AcquireAsync(_cancelTokenSource.Token); + + // reload our configs since they've likely changed by now + if (mutexExists) + { + App.Settings.Load(); + App.State.Load(); + } + + await CheckLatestVersion(); + + CheckInstallMigration(); + + // install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist + if (App.IsFirstRun || _latestVersionGuid != App.State.Prop.VersionGuid || !File.Exists(_playerLocation)) + await InstallLatestVersion(); + + if (App.IsFirstRun) + App.ShouldSaveConfigs = true; + + MigrateIntegrations(); + + await InstallWebView2(); + + App.FastFlags.Save(); + await ApplyModifications(); + + if (App.IsFirstRun || FreshInstall) + { + Register(); + RegisterProgramSize(); + } + + CheckInstall(); + + // at this point we've finished updating our configs + App.Settings.Save(); + App.State.Save(); + App.ShouldSaveConfigs = false; + + await mutex.ReleaseAsync(); + + if (App.IsFirstRun && App.IsNoLaunch) + Dialog?.ShowSuccess($"{App.ProjectName} has successfully installed"); + else if (!App.IsNoLaunch && !_cancelFired) + await StartRoblox(); + } + + private async Task CheckLatestVersion() + { + SetStatus("Connecting to Roblox..."); + + ClientVersion clientVersion = await RobloxDeployment.GetInfo(App.Settings.Prop.Channel); + + // briefly check if current channel is suitable to use + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) + { + string? switchDefaultPrompt = null; + ClientVersion? defaultChannelInfo = null; + + App.Logger.WriteLine($"[Bootstrapper::CheckLatestVersion] Checking if current channel is suitable to use..."); + + if (String.IsNullOrEmpty(switchDefaultPrompt)) + { + // this SUCKS + defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); + int defaultChannelVersion = Int32.Parse(defaultChannelInfo.Version.Split('.')[1]); + int currentChannelVersion = Int32.Parse(clientVersion.Version.Split('.')[1]); + + if (currentChannelVersion < defaultChannelVersion) + switchDefaultPrompt = $"Your current preferred channel ({App.Settings.Prop.Channel}) appears to no longer be receiving updates. Would you like to switch to {RobloxDeployment.DefaultChannel}?"; + } + + if (!String.IsNullOrEmpty(switchDefaultPrompt)) + { + MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic ? MessageBoxResult.Yes : App.ShowMessageBox(switchDefaultPrompt, MessageBoxImage.Question, MessageBoxButton.YesNo); + + if (result == MessageBoxResult.Yes) + { + App.Settings.Prop.Channel = RobloxDeployment.DefaultChannel; + App.Logger.WriteLine($"[DeployManager::SwitchToDefault] Changed Roblox release channel from {App.Settings.Prop.Channel} to {RobloxDeployment.DefaultChannel}"); + + if (defaultChannelInfo is null) + defaultChannelInfo = await RobloxDeployment.GetInfo(RobloxDeployment.DefaultChannel); + + clientVersion = defaultChannelInfo; + } + } + } + + _latestVersionGuid = clientVersion.VersionGuid; + _versionFolder = Path.Combine(Directories.Versions, _latestVersionGuid); + _versionPackageManifest = await PackageManifest.Get(_latestVersionGuid); + } + + private async Task StartRoblox() + { + SetStatus("Starting Roblox..."); + + if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) + { + Utilities.ShellExecute("https://www.roblox.com/games"); + Dialog?.CloseBootstrapper(); + return; + } + if (!File.Exists("C:\\Windows\\System32\\mfplat.dll")) { App.ShowMessageBox("Roblox requires the use of Windows Media Foundation components. You appear to be missing them, likely because you are using an N edition of Windows. Please install them first, and then launch Roblox.", MessageBoxImage.Error); Utilities.ShellExecute("https://support.microsoft.com/en-us/topic/media-feature-pack-list-for-windows-n-editions-c1c6fffa-d052-8338-7a79-a4bb980a700a"); Dialog?.CloseBootstrapper(); return; - } - - _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); - - if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) - _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); - - // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes - bool shouldWait = false; - - // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now - int gameClientPid; - using (Process gameClient = Process.Start(_playerLocation, _launchCommandLine)) - { - gameClientPid = gameClient.Id; - } - - List autocloseProcesses = new(); - RobloxActivity? activityWatcher = null; - DiscordRichPresence? richPresence = null; - ServerNotifier? serverNotifier = null; - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Started Roblox (PID {gameClientPid})"); - - using (SystemEvent startEvent = new("www.roblox.com/robloxStartedEvent")) - { - bool startEventFired = await startEvent.WaitForEvent(); - - startEvent.Close(); - - if (!startEventFired) - return; - } - - if (App.Settings.Prop.UseDiscordRichPresence || App.Settings.Prop.ShowServerDetails) - { - activityWatcher = new(); - shouldWait = true; - } - - if (App.Settings.Prop.UseDiscordRichPresence) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); - richPresence = new(activityWatcher!); - } - - if (App.Settings.Prop.ShowServerDetails) - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using server details notifier"); - serverNotifier = new(activityWatcher!); - } - - // launch custom integrations now - foreach (CustomIntegration integration in App.Settings.Prop.CustomIntegrations) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})"); - - try - { - Process process = Process.Start(integration.Location, integration.LaunchArgs); - - if (integration.AutoClose) - { - shouldWait = true; - autocloseProcesses.Add(process); - } - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Failed to launch integration '{integration.Name}'! ({ex.Message})"); - } - } - - // event fired, wait for 3 seconds then close - await Task.Delay(3000); - Dialog?.CloseBootstrapper(); - - // keep bloxstrap open in the background if needed - if (!shouldWait) - return; - - activityWatcher?.StartWatcher(); - - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); - - while (Process.GetProcesses().Any(x => x.Id == gameClientPid)) - await Task.Delay(1000); - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Roblox has exited"); - - richPresence?.Dispose(); - - foreach (Process process in autocloseProcesses) - { - if (process.HasExited) - continue; - - App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); - process.Kill(); - } - } - - public void CancelInstall() - { - if (!_isInstalling) - { - App.Terminate(ERROR_INSTALL_USEREXIT); - return; - } - - App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); - - _cancelTokenSource.Cancel(); - _cancelFired = true; - - try - { - // clean up install - if (App.IsFirstRun) - Directory.Delete(Directories.Base, true); - else if (Directory.Exists(_versionFolder)) - Directory.Delete(_versionFolder, true); - } - catch (Exception ex) - { - App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); - App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {ex}"); - } - - App.Terminate(ERROR_INSTALL_USEREXIT); - } - #endregion - - #region App Install - public static void Register() - { - using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) - { - applicationKey.SetValue("InstallLocation", Directories.Base); - } - - // set uninstall key - using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")) - { - uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); - uninstallKey.SetValue("DisplayName", App.ProjectName); - uninstallKey.SetValue("DisplayVersion", App.Version); - - if (uninstallKey.GetValue("InstallDate") is null) - uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); - - uninstallKey.SetValue("InstallLocation", Directories.Base); - uninstallKey.SetValue("NoRepair", 1); - uninstallKey.SetValue("Publisher", "pizzaboxer"); - uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); - uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); - uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); - uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); - uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); - } - - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); - } - - public void RegisterProgramSize() - { - App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); - - using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); - - // sum compressed and uncompressed package sizes and convert to kilobytes - int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; - - uninstallKey.SetValue("EstimatedSize", totalSize); - - App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); - } - - private void CheckInstallMigration() - { - // check if we've changed our install location since the last time we started - // in which case, we'll have to copy over all our folders so we don't lose any mods and stuff - - using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true); - - string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation"); - - if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base) - return; - - SetStatus("Migrating install location..."); - - if (Directory.Exists(oldInstallLocation)) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}..."); - - foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories)) - { - string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1); - string newFileLocation = Path.Combine(Directories.Base, relativeFile); - string? newDirectory = Path.GetDirectoryName(newFileLocation); - - try - { - if (!String.IsNullOrEmpty(newDirectory)) - Directory.CreateDirectory(newDirectory); - - File.Move(oldFileLocation, newFileLocation, true); - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}"); - } - } - - try - { - Directory.Delete(oldInstallLocation, true); - App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location"); - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}"); - } - } - - applicationKey.DeleteValue("OldInstallLocation"); - - // allow shortcuts to be re-registered - if (Directory.Exists(Directories.StartMenu)) - Directory.Delete(Directories.StartMenu, true); - - if (File.Exists(DesktopShortcutLocation)) - { - File.Delete(DesktopShortcutLocation); - App.Settings.Prop.CreateDesktopIcon = true; - } - - App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!"); - } - - public static void CheckInstall() - { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); - - // check if launch uri is set to our bootstrapper - // this doesn't go under register, so we check every launch - // just in case the stock bootstrapper changes it back - - ProtocolHandler.Register("roblox", "Roblox", Directories.Application); - ProtocolHandler.Register("roblox-player", "Roblox", Directories.Application); - - // in case the user is reinstalling - if (File.Exists(Directories.Application) && App.IsFirstRun) - File.Delete(Directories.Application); - - // check to make sure bootstrapper is in the install folder - if (!File.Exists(Directories.Application) && Environment.ProcessPath is not null) - File.Copy(Environment.ProcessPath, Directories.Application); - - // this SHOULD go under Register(), - // but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall - // maybe in a later version? - if (!Directory.Exists(Directories.StartMenu)) - { - Directory.CreateDirectory(Directories.StartMenu); - - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(Path.Combine(Directories.StartMenu, "Play Roblox.lnk")); - - ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) - .WriteToFile(Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk")); - } - else - { - // v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu" - string oldMenuShortcut = Path.Combine(Directories.StartMenu, $"Configure {App.ProjectName}.lnk"); - string newMenuShortcut = Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk"); - - if (File.Exists(oldMenuShortcut)) - File.Delete(oldMenuShortcut); - - if (!File.Exists(newMenuShortcut)) - ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) - .WriteToFile(newMenuShortcut); - } - - if (App.Settings.Prop.CreateDesktopIcon) - { - if (!File.Exists(DesktopShortcutLocation)) - { - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(DesktopShortcutLocation); - } - - // one-time toggle, set it back to false - App.Settings.Prop.CreateDesktopIcon = false; - } - } - - private async Task CheckForUpdates() - { - // don't update if there's another instance running (likely running in the background) - if (Process.GetProcessesByName(App.ProjectName).Count() > 1) - { - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); - return; - } - - string currentVersion = $"{App.ProjectName} v{App.Version}"; - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); - - var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); - - if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) - { - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); - return; - } - - SetStatus($"Getting the latest {App.ProjectName}..."); - - // 64-bit is always the first option - GithubReleaseAsset asset = releaseInfo.Assets[0]; - string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); - - if (!File.Exists(downloadLocation)) - { - var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl); - - await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); - } - - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); - - ProcessStartInfo startInfo = new() - { - FileName = downloadLocation, - }; - - foreach (string arg in App.LaunchArgs) - startInfo.ArgumentList.Add(arg); - - App.Settings.Save(); - - Process.Start(startInfo); - - Environment.Exit(0); - } - - private void Uninstall() - { - // prompt to shutdown roblox if its currently running - if (Process.GetProcessesByName(App.RobloxAppName).Any()) - { - App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); - - Dialog?.PromptShutdown(); - - try - { - foreach (Process process in Process.GetProcessesByName("RobloxPlayerBeta")) - { - process.CloseMainWindow(); - process.Close(); - } - } - catch (Exception ex) - { - App.Logger.WriteLine($"[Bootstrapper::ShutdownIfRobloxRunning] Failed to close process! {ex}"); - } - - App.Logger.WriteLine($"[Bootstrapper::Uninstall] All Roblox processes closed"); - } - - SetStatus($"Uninstalling {App.ProjectName}..."); - - //App.Settings.ShouldSave = false; - App.ShouldSaveConfigs = false; - - // check if stock bootstrapper is still installed - RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player"); - if (bootstrapperKey is null) - { - ProtocolHandler.Unregister("roblox"); - ProtocolHandler.Unregister("roblox-player"); - } - else - { - // revert launch uri handler to stock bootstrapper - - string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe"; - - ProtocolHandler.Register("roblox", "Roblox", bootstrapperLocation); - ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation); - } - - try - { - // delete application key - Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"); - - // delete start menu folder - Directory.Delete(Directories.StartMenu, true); - - // delete desktop shortcut - File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); - - // delete uninstall key - Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); - - // delete installation folder - // (should delete everything except bloxstrap itself) - Directory.Delete(Directories.Base, true); - } - catch (Exception ex) - { - App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); - } - - Action? callback = null; - - if (Directory.Exists(Directories.Base)) - { - callback = () => - { - // this is definitely one of the workaround hacks of all time - // could antiviruses falsely detect this as malicious behaviour though? - // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" - - Process.Start(new ProcessStartInfo() - { - FileName = "cmd.exe", - Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", - UseShellExecute = true, - WindowStyle = ProcessWindowStyle.Hidden - }); - }; - } - - Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); - } - #endregion - - #region Roblox Install - private async Task InstallLatestVersion() - { - _isInstalling = true; - - SetStatus(FreshInstall ? "Installing Roblox..." : "Upgrading Roblox..."); - - Directory.CreateDirectory(Directories.Base); - Directory.CreateDirectory(Directories.Downloads); - Directory.CreateDirectory(Directories.Versions); - - // package manifest states packed size and uncompressed size in exact bytes - // packed size only matters if we don't already have the package cached on disk - string[] cachedPackages = Directory.GetFiles(Directories.Downloads); - int totalSizeRequired = _versionPackageManifest.Where(x => !cachedPackages.Contains(x.Signature)).Sum(x => x.PackedSize) + _versionPackageManifest.Sum(x => x.Size); - - if (Utilities.GetFreeDiskSpace(Directories.Base) < totalSizeRequired) - { - App.ShowMessageBox($"{App.ProjectName} does not have enough disk space to download and install Roblox. Please free up some disk space and try again.", MessageBoxImage.Error); - App.Terminate(ERROR_INSTALL_FAILURE); - return; - } - - if (Dialog is not null) - { - Dialog.CancelEnabled = true; - Dialog.ProgressStyle = ProgressBarStyle.Continuous; - } - - // compute total bytes to download - _progressIncrement = (double)100 / _versionPackageManifest.Sum(package => package.PackedSize); - - foreach (Package package in _versionPackageManifest) - { - if (_cancelFired) - return; - - // download all the packages synchronously - await DownloadPackage(package); - - // we'll extract the runtime installer later if we need to - if (package.Name == "WebView2RuntimeInstaller.zip") - continue; - - // extract the package immediately after download asynchronously - // discard is just used to suppress the warning - Task _ = ExtractPackage(package); - } - - if (_cancelFired) - return; - - // allow progress bar to 100% before continuing (purely ux reasons lol) - await Task.Delay(1000); - - if (Dialog is not null) - { - Dialog.ProgressStyle = ProgressBarStyle.Marquee; - SetStatus("Configuring Roblox..."); - } - - // wait for all packages to finish extracting, with an exception for the webview2 runtime installer - while (_packagesExtracted < _versionPackageManifest.Where(x => x.Name != "WebView2RuntimeInstaller.zip").Count()) - { - await Task.Delay(100); - } - - string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); - await File.WriteAllTextAsync(appSettingsLocation, AppSettings); - - if (_cancelFired) - return; - - if (!FreshInstall) - { - // let's take this opportunity to delete any packages we don't need anymore - foreach (string filename in cachedPackages) - { - if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) - { - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); - File.Delete(filename); - } - } - - string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); - - // move old compatibility flags for the old location - using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) - { - string oldGameClientLocation = Path.Combine(oldVersionFolder, "RobloxPlayerBeta.exe"); - string? appFlags = (string?)appFlagsKey.GetValue(oldGameClientLocation); - - if (appFlags is not null) - { - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Migrating app compatibility flags from {oldGameClientLocation} to {_playerLocation}..."); - appFlagsKey.SetValue(_playerLocation, appFlags); - appFlagsKey.DeleteValue(oldGameClientLocation); - } - } - - // delete any old version folders - // we only do this if roblox isnt running just in case an update happened - // while they were launching a second instance or something idk - if (!Process.GetProcessesByName(App.RobloxAppName).Any()) - { - foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) - { - if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) - continue; - - App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); - dir.Delete(true); - } - } - } - - App.State.Prop.VersionGuid = _latestVersionGuid; - - // don't register program size until the program is registered, which will be done after this - if (!App.IsFirstRun && !FreshInstall) - RegisterProgramSize(); - - if (Dialog is not null) - Dialog.CancelEnabled = false; - - _isInstalling = false; - } - - private async Task InstallWebView2() - { - // check if the webview2 runtime needs to be installed - // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu - // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed - - using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - using RegistryKey? hkcuKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); - - if (hklmKey is not null || hkcuKey is not null) - return; - - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); - - string baseDirectory = Path.Combine(_versionFolder, "WebView2RuntimeInstaller"); - - if (!Directory.Exists(baseDirectory)) - { - Package? package = _versionPackageManifest.Find(x => x.Name == "WebView2RuntimeInstaller.zip"); - - if (package is null) - { - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Aborted runtime install because package does not exist, has WebView2 been added in this Roblox version yet?"); - return; - } - - await ExtractPackage(package); - } - - SetStatus("Installing WebView2, please wait..."); - - ProcessStartInfo startInfo = new() - { - WorkingDirectory = baseDirectory, - FileName = Path.Combine(baseDirectory, "MicrosoftEdgeWebview2Setup.exe"), - Arguments = "/silent /install" - }; - - await Process.Start(startInfo)!.WaitForExitAsync(); - - App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Finished installing runtime"); - } - - public static void MigrateIntegrations() - { - // v2.2.0 - remove rbxfpsunlocker - string rbxfpsunlocker = Path.Combine(Directories.Integrations, "rbxfpsunlocker"); - - if (Directory.Exists(rbxfpsunlocker)) - Directory.Delete(rbxfpsunlocker, true); - - // v2.3.0 - remove reshade - string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); - string configLocation = Path.Combine(Directories.Modifications, "ReShade.ini"); - - if (File.Exists(injectorLocation)) - { - App.ShowMessageBox( - "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ - "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", - MessageBoxImage.Warning - ); - - File.Delete(injectorLocation); - } - - if (File.Exists(configLocation)) - File.Delete(configLocation); - } - - private async Task ApplyModifications() - { - SetStatus("Applying Roblox modifications..."); - - // set executable flags for fullscreen optimizations - App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking executable flags..."); - using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) - { - const string flag = " DISABLEDXMAXIMIZEDWINDOWEDMODE"; - string? appFlags = (string?)appFlagsKey.GetValue(_playerLocation); - - if (App.Settings.Prop.DisableFullscreenOptimizations) - { - if (appFlags is null) - appFlagsKey.SetValue(_playerLocation, $"~{flag}"); - else if (!appFlags.Contains(flag)) - appFlagsKey.SetValue(_playerLocation, appFlags + flag); - } - else if (appFlags is not null && appFlags.Contains(flag)) - { - // if there's more than one space, there's more flags set we need to preserve - if (appFlags.Split(' ').Length > 2) - appFlagsKey.SetValue(_playerLocation, appFlags.Remove(appFlags.IndexOf(flag), flag.Length)); - else - appFlagsKey.DeleteValue(_playerLocation); - } - } - - // handle file mods - App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking file mods..."); - string modFolder = Path.Combine(Directories.Modifications); - - // manifest has been moved to State.json - File.Delete(Path.Combine(Directories.Base, "ModManifest.txt")); - - List modFolderFiles = new(); - - if (!Directory.Exists(modFolder)) - Directory.CreateDirectory(modFolder); - - await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); - await CheckModPreset(App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"), @"ExtraContent\places\Mobile.rbxl", ""); - - // emoji presets are downloaded remotely from github due to how large they are - string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); - - if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) - { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - App.State.Prop.CurrentEmojiType = EmojiType.Default; - } - else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) - { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); - - var response = await App.HttpClient.GetAsync(remoteEmojiLocation); - await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); - - App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; - } - - foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) - { - // get relative directory path - string relativeFile = file.Substring(modFolder.Length + 1); - - // v1.7.0 - README has been moved to the preferences menu now - if (relativeFile == "README.txt") - { - File.Delete(file); - continue; - } - - modFolderFiles.Add(relativeFile); - } - - // copy and overwrite - foreach (string file in modFolderFiles) - { - string fileModFolder = Path.Combine(modFolder, file); - string fileVersionFolder = Path.Combine(_versionFolder, file); - - if (File.Exists(fileVersionFolder)) - { - if (Utility.MD5Hash.FromFile(fileModFolder) == Utility.MD5Hash.FromFile(fileVersionFolder)) - continue; - } - - string? directory = Path.GetDirectoryName(fileVersionFolder); - - if (directory is null) - continue; - - Directory.CreateDirectory(directory); - - File.Copy(fileModFolder, fileVersionFolder, true); - File.SetAttributes(fileVersionFolder, File.GetAttributes(fileModFolder) & ~FileAttributes.ReadOnly); - } - - // the manifest is primarily here to keep track of what files have been - // deleted from the modifications folder, so that we know when to restore the original files from the downloaded packages - // now check for files that have been deleted from the mod folder according to the manifest - foreach (string fileLocation in App.State.Prop.ModManifest) - { - if (modFolderFiles.Contains(fileLocation)) - continue; - - KeyValuePair packageDirectory; - - try - { - packageDirectory = PackageDirectories.First(x => x.Value != "" && fileLocation.StartsWith(x.Value)); - } - catch (InvalidOperationException) - { - // package doesn't exist, likely mistakenly placed file - string versionFileLocation = Path.Combine(_versionFolder, fileLocation); - - if (File.Exists(versionFileLocation)) - File.Delete(versionFileLocation); - - continue; - } - - // restore original file - string fileName = fileLocation.Substring(packageDirectory.Value.Length); - ExtractFileFromPackage(packageDirectory.Key, fileName); - } - - App.State.Prop.ModManifest = modFolderFiles; - App.State.Save(); - } - - private static async Task CheckModPreset(bool condition, string location, string name) - { - string modFolderLocation = Path.Combine(Directories.Modifications, location); - byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); - - if (condition) - { - if (!File.Exists(modFolderLocation)) - { - string? directory = Path.GetDirectoryName(modFolderLocation); - - if (directory is null) - return; - - Directory.CreateDirectory(directory); - - await File.WriteAllBytesAsync(modFolderLocation, binaryData); - } - } - else if (File.Exists(modFolderLocation) && Utility.MD5Hash.FromFile(modFolderLocation) == Utility.MD5Hash.FromBytes(binaryData)) - { - File.Delete(modFolderLocation); - } - } - - private async Task DownloadPackage(Package package) - { - if (_cancelFired) - return; - - string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}"); - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string robloxPackageLocation = Path.Combine(Directories.LocalAppData, "Roblox", "Downloads", package.Signature); - - if (File.Exists(packageLocation)) - { - FileInfo file = new(packageLocation); - - string calculatedMD5 = Utility.MD5Hash.FromFile(packageLocation); - - if (calculatedMD5 != package.Signature) - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); - file.Delete(); - } - else - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); - _totalDownloadedBytes += package.PackedSize; - UpdateProgressbar(); - return; - } - } - else if (File.Exists(robloxPackageLocation)) - { - // let's cheat! if the stock bootstrapper already previously downloaded the file, - // then we can just copy the one from there - - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); - File.Copy(robloxPackageLocation, packageLocation); - _totalDownloadedBytes += package.PackedSize; - UpdateProgressbar(); - return; - } - - if (!File.Exists(packageLocation)) - { - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); - - { - var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); - var buffer = new byte[4096]; - - await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token); - await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete); - - while (true) - { - if (_cancelFired) - { - stream.Close(); - fileStream.Close(); - return; - } - - var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cancelTokenSource.Token); - - if (bytesRead == 0) - break; // we're done - - await fileStream.WriteAsync(buffer, 0, bytesRead, _cancelTokenSource.Token); - - _totalDownloadedBytes += bytesRead; - UpdateProgressbar(); - } - } - - App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); - } - } - - private async Task ExtractPackage(Package package) - { - if (_cancelFired) - return; - - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); - string extractPath; - - App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); - - using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) - { - foreach (ZipArchiveEntry entry in archive.Entries) - { - if (_cancelFired) - return; - - if (entry.FullName.EndsWith('\\')) - continue; - - extractPath = Path.Combine(packageFolder, entry.FullName); - - //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); - - string? directory = Path.GetDirectoryName(extractPath); - - if (directory is null) - continue; - - Directory.CreateDirectory(directory); - - await Task.Run(() => entry.ExtractToFile(extractPath, true)); - } - } - - App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); - - _packagesExtracted += 1; - } - - private void ExtractFileFromPackage(string packageName, string fileName) - { - Package? package = _versionPackageManifest.Find(x => x.Name == packageName); - - if (package is null) - return; - - DownloadPackage(package).GetAwaiter().GetResult(); - - string packageLocation = Path.Combine(Directories.Downloads, package.Signature); - string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); - - using ZipArchive archive = ZipFile.OpenRead(packageLocation); - - ZipArchiveEntry? entry = archive.Entries.FirstOrDefault(x => x.FullName == fileName); - - if (entry is null) - return; - - string fileLocation = Path.Combine(packageFolder, entry.FullName); - - File.Delete(fileLocation); - - entry.ExtractToFile(fileLocation); - } - #endregion - } -} + } + + _launchCommandLine = _launchCommandLine.Replace("LAUNCHTIMEPLACEHOLDER", DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString()); + + if (App.Settings.Prop.Channel.ToLowerInvariant() != RobloxDeployment.DefaultChannel.ToLowerInvariant()) + _launchCommandLine += " -channel " + App.Settings.Prop.Channel.ToLowerInvariant(); + + // whether we should wait for roblox to exit to handle stuff in the background or clean up after roblox closes + bool shouldWait = false; + + // v2.2.0 - byfron will trip if we keep a process handle open for over a minute, so we're doing this now + int gameClientPid; + using (Process gameClient = Process.Start(_playerLocation, _launchCommandLine)) + { + gameClientPid = gameClient.Id; + } + + List autocloseProcesses = new(); + RobloxActivity? activityWatcher = null; + DiscordRichPresence? richPresence = null; + ServerNotifier? serverNotifier = null; + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Started Roblox (PID {gameClientPid})"); + + using (SystemEvent startEvent = new("www.roblox.com/robloxStartedEvent")) + { + bool startEventFired = await startEvent.WaitForEvent(); + + startEvent.Close(); + + if (!startEventFired) + return; + } + + if (App.Settings.Prop.UseDiscordRichPresence || App.Settings.Prop.ShowServerDetails) + { + activityWatcher = new(); + shouldWait = true; + } + + if (App.Settings.Prop.UseDiscordRichPresence) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); + richPresence = new(activityWatcher!); + } + + if (App.Settings.Prop.ShowServerDetails) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using server details notifier"); + serverNotifier = new(activityWatcher!); + } + + // launch custom integrations now + foreach (CustomIntegration integration in App.Settings.Prop.CustomIntegrations) + { + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})"); + + try + { + Process process = Process.Start(integration.Location, integration.LaunchArgs); + + if (integration.AutoClose) + { + shouldWait = true; + autocloseProcesses.Add(process); + } + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Failed to launch integration '{integration.Name}'! ({ex.Message})"); + } + } + + // event fired, wait for 3 seconds then close + await Task.Delay(3000); + Dialog?.CloseBootstrapper(); + + // keep bloxstrap open in the background if needed + if (!shouldWait) + return; + + activityWatcher?.StartWatcher(); + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); + + while (Process.GetProcesses().Any(x => x.Id == gameClientPid)) + await Task.Delay(1000); + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Roblox has exited"); + + richPresence?.Dispose(); + + foreach (Process process in autocloseProcesses) + { + if (process.HasExited) + continue; + + App.Logger.WriteLine($"[Bootstrapper::StartRoblox] Autoclosing process '{process.ProcessName}' (PID {process.Id})"); + process.Kill(); + } + } + + public void CancelInstall() + { + if (!_isInstalling) + { + App.Terminate(ERROR_INSTALL_USEREXIT); + return; + } + + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); + + _cancelTokenSource.Cancel(); + _cancelFired = true; + + try + { + // clean up install + if (App.IsFirstRun) + Directory.Delete(Directories.Base, true); + else if (Directory.Exists(_versionFolder)) + Directory.Delete(_versionFolder, true); + } + catch (Exception ex) + { + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); + App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {ex}"); + } + + App.Terminate(ERROR_INSTALL_USEREXIT); + } + #endregion + + #region App Install + public static void Register() + { + using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) + { + applicationKey.SetValue("InstallLocation", Directories.Base); + } + + // set uninstall key + using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")) + { + uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); + uninstallKey.SetValue("DisplayName", App.ProjectName); + uninstallKey.SetValue("DisplayVersion", App.Version); + + if (uninstallKey.GetValue("InstallDate") is null) + uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); + + uninstallKey.SetValue("InstallLocation", Directories.Base); + uninstallKey.SetValue("NoRepair", 1); + uninstallKey.SetValue("Publisher", "pizzaboxer"); + uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); + uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); + uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); + uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); + uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); + } + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application"); + } + + public void RegisterProgramSize() + { + App.Logger.WriteLine("[Bootstrapper::RegisterProgramSize] Registering approximate program size..."); + + using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{App.ProjectName}"); + + // sum compressed and uncompressed package sizes and convert to kilobytes + int totalSize = (_versionPackageManifest.Sum(x => x.Size) + _versionPackageManifest.Sum(x => x.PackedSize)) / 1000; + + uninstallKey.SetValue("EstimatedSize", totalSize); + + App.Logger.WriteLine($"[Bootstrapper::RegisterProgramSize] Registered as {totalSize} KB"); + } + + private void CheckInstallMigration() + { + // check if we've changed our install location since the last time we started + // in which case, we'll have to copy over all our folders so we don't lose any mods and stuff + + using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true); + + string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation"); + + if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base) + return; + + SetStatus("Migrating install location..."); + + if (Directory.Exists(oldInstallLocation)) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}..."); + + foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories)) + { + string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1); + string newFileLocation = Path.Combine(Directories.Base, relativeFile); + string? newDirectory = Path.GetDirectoryName(newFileLocation); + + try + { + if (!String.IsNullOrEmpty(newDirectory)) + Directory.CreateDirectory(newDirectory); + + File.Move(oldFileLocation, newFileLocation, true); + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}"); + } + } + + try + { + Directory.Delete(oldInstallLocation, true); + App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location"); + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}"); + } + } + + applicationKey.DeleteValue("OldInstallLocation"); + + // allow shortcuts to be re-registered + if (Directory.Exists(Directories.StartMenu)) + Directory.Delete(Directories.StartMenu, true); + + if (File.Exists(DesktopShortcutLocation)) + { + File.Delete(DesktopShortcutLocation); + App.Settings.Prop.CreateDesktopIcon = true; + } + + App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!"); + } + + public static void CheckInstall() + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); + + // check if launch uri is set to our bootstrapper + // this doesn't go under register, so we check every launch + // just in case the stock bootstrapper changes it back + + ProtocolHandler.Register("roblox", "Roblox", Directories.Application); + ProtocolHandler.Register("roblox-player", "Roblox", Directories.Application); + + // in case the user is reinstalling + if (File.Exists(Directories.Application) && App.IsFirstRun) + File.Delete(Directories.Application); + + // check to make sure bootstrapper is in the install folder + if (!File.Exists(Directories.Application) && Environment.ProcessPath is not null) + File.Copy(Environment.ProcessPath, Directories.Application); + + // this SHOULD go under Register(), + // but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall + // maybe in a later version? + if (!Directory.Exists(Directories.StartMenu)) + { + Directory.CreateDirectory(Directories.StartMenu); + + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(Path.Combine(Directories.StartMenu, "Play Roblox.lnk")); + + ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) + .WriteToFile(Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk")); + } + else + { + // v2.0.0 - rebadge configuration menu as just "Bloxstrap Menu" + string oldMenuShortcut = Path.Combine(Directories.StartMenu, $"Configure {App.ProjectName}.lnk"); + string newMenuShortcut = Path.Combine(Directories.StartMenu, $"{App.ProjectName} Menu.lnk"); + + if (File.Exists(oldMenuShortcut)) + File.Delete(oldMenuShortcut); + + if (!File.Exists(newMenuShortcut)) + ShellLink.Shortcut.CreateShortcut(Directories.Application, "-menu", Directories.Application, 0) + .WriteToFile(newMenuShortcut); + } + + if (App.Settings.Prop.CreateDesktopIcon) + { + if (!File.Exists(DesktopShortcutLocation)) + { + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(DesktopShortcutLocation); + } + + // one-time toggle, set it back to false + App.Settings.Prop.CreateDesktopIcon = false; + } + } + + private async Task CheckForUpdates() + { + // don't update if there's another instance running (likely running in the background) + if (Process.GetProcessesByName(App.ProjectName).Count() > 1) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); + return; + } + + string currentVersion = $"{App.ProjectName} v{App.Version}"; + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); + + var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); + + if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); + return; + } + + SetStatus($"Getting the latest {App.ProjectName}..."); + + // 64-bit is always the first option + GithubReleaseAsset asset = releaseInfo.Assets[0]; + string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); + + if (!File.Exists(downloadLocation)) + { + var response = await App.HttpClient.GetAsync(asset.BrowserDownloadUrl); + + await using var fileStream = new FileStream(downloadLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + } + + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); + + ProcessStartInfo startInfo = new() + { + FileName = downloadLocation, + }; + + foreach (string arg in App.LaunchArgs) + startInfo.ArgumentList.Add(arg); + + App.Settings.Save(); + + Process.Start(startInfo); + + Environment.Exit(0); + } + + private void Uninstall() + { + // prompt to shutdown roblox if its currently running + if (Process.GetProcessesByName(App.RobloxAppName).Any()) + { + App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); + + Dialog?.PromptShutdown(); + + try + { + foreach (Process process in Process.GetProcessesByName("RobloxPlayerBeta")) + { + process.CloseMainWindow(); + process.Close(); + } + } + catch (Exception ex) + { + App.Logger.WriteLine($"[Bootstrapper::ShutdownIfRobloxRunning] Failed to close process! {ex}"); + } + + App.Logger.WriteLine($"[Bootstrapper::Uninstall] All Roblox processes closed"); + } + + SetStatus($"Uninstalling {App.ProjectName}..."); + + //App.Settings.ShouldSave = false; + App.ShouldSaveConfigs = false; + + // check if stock bootstrapper is still installed + RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player"); + if (bootstrapperKey is null) + { + ProtocolHandler.Unregister("roblox"); + ProtocolHandler.Unregister("roblox-player"); + } + else + { + // revert launch uri handler to stock bootstrapper + + string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe"; + + ProtocolHandler.Register("roblox", "Roblox", bootstrapperLocation); + ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation); + } + + try + { + // delete application key + Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"); + + // delete start menu folder + Directory.Delete(Directories.StartMenu, true); + + // delete desktop shortcut + File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); + + // delete uninstall key + Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); + + // delete installation folder + // (should delete everything except bloxstrap itself) + Directory.Delete(Directories.Base, true); + } + catch (Exception ex) + { + App.Logger.WriteLine($"Could not fully uninstall! ({ex})"); + } + + Action? callback = null; + + if (Directory.Exists(Directories.Base)) + { + callback = () => + { + // this is definitely one of the workaround hacks of all time + // could antiviruses falsely detect this as malicious behaviour though? + // "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder" + + Process.Start(new ProcessStartInfo() + { + FileName = "cmd.exe", + Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"", + UseShellExecute = true, + WindowStyle = ProcessWindowStyle.Hidden + }); + }; + } + + Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled", callback); + } + #endregion + + #region Roblox Install + private async Task InstallLatestVersion() + { + _isInstalling = true; + + SetStatus(FreshInstall ? "Installing Roblox..." : "Upgrading Roblox..."); + + Directory.CreateDirectory(Directories.Base); + Directory.CreateDirectory(Directories.Downloads); + Directory.CreateDirectory(Directories.Versions); + + // package manifest states packed size and uncompressed size in exact bytes + // packed size only matters if we don't already have the package cached on disk + string[] cachedPackages = Directory.GetFiles(Directories.Downloads); + int totalSizeRequired = _versionPackageManifest.Where(x => !cachedPackages.Contains(x.Signature)).Sum(x => x.PackedSize) + _versionPackageManifest.Sum(x => x.Size); + + if (Utilities.GetFreeDiskSpace(Directories.Base) < totalSizeRequired) + { + App.ShowMessageBox($"{App.ProjectName} does not have enough disk space to download and install Roblox. Please free up some disk space and try again.", MessageBoxImage.Error); + App.Terminate(ERROR_INSTALL_FAILURE); + return; + } + + if (Dialog is not null) + { + Dialog.CancelEnabled = true; + Dialog.ProgressStyle = ProgressBarStyle.Continuous; + } + + // compute total bytes to download + _progressIncrement = (double)100 / _versionPackageManifest.Sum(package => package.PackedSize); + + foreach (Package package in _versionPackageManifest) + { + if (_cancelFired) + return; + + // download all the packages synchronously + await DownloadPackage(package); + + // we'll extract the runtime installer later if we need to + if (package.Name == "WebView2RuntimeInstaller.zip") + continue; + + // extract the package immediately after download asynchronously + // discard is just used to suppress the warning + Task _ = ExtractPackage(package); + } + + if (_cancelFired) + return; + + // allow progress bar to 100% before continuing (purely ux reasons lol) + await Task.Delay(1000); + + if (Dialog is not null) + { + Dialog.ProgressStyle = ProgressBarStyle.Marquee; + SetStatus("Configuring Roblox..."); + } + + // wait for all packages to finish extracting, with an exception for the webview2 runtime installer + while (_packagesExtracted < _versionPackageManifest.Where(x => x.Name != "WebView2RuntimeInstaller.zip").Count()) + { + await Task.Delay(100); + } + + string appSettingsLocation = Path.Combine(_versionFolder, "AppSettings.xml"); + await File.WriteAllTextAsync(appSettingsLocation, AppSettings); + + if (_cancelFired) + return; + + if (!FreshInstall) + { + // let's take this opportunity to delete any packages we don't need anymore + foreach (string filename in cachedPackages) + { + if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) + { + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Deleting unused package {filename}"); + File.Delete(filename); + } + } + + string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); + + // move old compatibility flags for the old location + using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) + { + string oldGameClientLocation = Path.Combine(oldVersionFolder, "RobloxPlayerBeta.exe"); + string? appFlags = (string?)appFlagsKey.GetValue(oldGameClientLocation); + + if (appFlags is not null) + { + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Migrating app compatibility flags from {oldGameClientLocation} to {_playerLocation}..."); + appFlagsKey.SetValue(_playerLocation, appFlags); + appFlagsKey.DeleteValue(oldGameClientLocation); + } + } + + // delete any old version folders + // we only do this if roblox isnt running just in case an update happened + // while they were launching a second instance or something idk + if (!Process.GetProcessesByName(App.RobloxAppName).Any()) + { + foreach (DirectoryInfo dir in new DirectoryInfo(Directories.Versions).GetDirectories()) + { + if (dir.Name == _latestVersionGuid || !dir.Name.StartsWith("version-")) + continue; + + App.Logger.WriteLine($"[Bootstrapper::InstallLatestVersion] Removing old version folder for {dir.Name}"); + dir.Delete(true); + } + } + } + + App.State.Prop.VersionGuid = _latestVersionGuid; + + // don't register program size until the program is registered, which will be done after this + if (!App.IsFirstRun && !FreshInstall) + RegisterProgramSize(); + + if (Dialog is not null) + Dialog.CancelEnabled = false; + + _isInstalling = false; + } + + private async Task InstallWebView2() + { + // check if the webview2 runtime needs to be installed + // webview2 can either be installed be per-user or globally, so we need to check in both hklm and hkcu + // https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#detect-if-a-suitable-webview2-runtime-is-already-installed + + using RegistryKey? hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + using RegistryKey? hkcuKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"); + + if (hklmKey is not null || hkcuKey is not null) + return; + + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Installing runtime..."); + + string baseDirectory = Path.Combine(_versionFolder, "WebView2RuntimeInstaller"); + + if (!Directory.Exists(baseDirectory)) + { + Package? package = _versionPackageManifest.Find(x => x.Name == "WebView2RuntimeInstaller.zip"); + + if (package is null) + { + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Aborted runtime install because package does not exist, has WebView2 been added in this Roblox version yet?"); + return; + } + + await ExtractPackage(package); + } + + SetStatus("Installing WebView2, please wait..."); + + ProcessStartInfo startInfo = new() + { + WorkingDirectory = baseDirectory, + FileName = Path.Combine(baseDirectory, "MicrosoftEdgeWebview2Setup.exe"), + Arguments = "/silent /install" + }; + + await Process.Start(startInfo)!.WaitForExitAsync(); + + App.Logger.WriteLine($"[Bootstrapper::InstallWebView2] Finished installing runtime"); + } + + public static void MigrateIntegrations() + { + // v2.2.0 - remove rbxfpsunlocker + string rbxfpsunlocker = Path.Combine(Directories.Integrations, "rbxfpsunlocker"); + + if (Directory.Exists(rbxfpsunlocker)) + Directory.Delete(rbxfpsunlocker, true); + + // v2.3.0 - remove reshade + string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); + string configLocation = Path.Combine(Directories.Modifications, "ReShade.ini"); + + if (File.Exists(injectorLocation)) + { + App.ShowMessageBox( + "Roblox has now finished rolling out the new game client update, featuring 64-bit support and the Hyperion anticheat. ReShade does not work with this update, and so it has now been disabled and removed from Bloxstrap.\n\n"+ + "Your ReShade configuration files will still be saved, and you can locate them by opening the folder where Bloxstrap is installed to, and navigating to the Integrations folder. You can choose to delete these if you want.", + MessageBoxImage.Warning + ); + + File.Delete(injectorLocation); + } + + if (File.Exists(configLocation)) + File.Delete(configLocation); + } + + private async Task ApplyModifications() + { + SetStatus("Applying Roblox modifications..."); + + // set executable flags for fullscreen optimizations + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking executable flags..."); + using (RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers")) + { + const string flag = " DISABLEDXMAXIMIZEDWINDOWEDMODE"; + string? appFlags = (string?)appFlagsKey.GetValue(_playerLocation); + + if (App.Settings.Prop.DisableFullscreenOptimizations) + { + if (appFlags is null) + appFlagsKey.SetValue(_playerLocation, $"~{flag}"); + else if (!appFlags.Contains(flag)) + appFlagsKey.SetValue(_playerLocation, appFlags + flag); + } + else if (appFlags is not null && appFlags.Contains(flag)) + { + // if there's more than one space, there's more flags set we need to preserve + if (appFlags.Split(' ').Length > 2) + appFlagsKey.SetValue(_playerLocation, appFlags.Remove(appFlags.IndexOf(flag), flag.Length)); + else + appFlagsKey.DeleteValue(_playerLocation); + } + } + + // handle file mods + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Checking file mods..."); + string modFolder = Path.Combine(Directories.Modifications); + + // manifest has been moved to State.json + File.Delete(Path.Combine(Directories.Base, "ModManifest.txt")); + + List modFolderFiles = new(); + + if (!Directory.Exists(modFolder)) + Directory.CreateDirectory(modFolder); + + await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); + await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); + await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"), @"ExtraContent\places\Mobile.rbxl", ""); + + // emoji presets are downloaded remotely from github due to how large they are + string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); + + if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + App.State.Prop.CurrentEmojiType = EmojiType.Default; + } + else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) + { + if (File.Exists(emojiFontLocation)) + File.Delete(emojiFontLocation); + + string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); + + var response = await App.HttpClient.GetAsync(remoteEmojiLocation); + await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + + App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; + } + + foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) + { + // get relative directory path + string relativeFile = file.Substring(modFolder.Length + 1); + + // v1.7.0 - README has been moved to the preferences menu now + if (relativeFile == "README.txt") + { + File.Delete(file); + continue; + } + + modFolderFiles.Add(relativeFile); + } + + // copy and overwrite + foreach (string file in modFolderFiles) + { + string fileModFolder = Path.Combine(modFolder, file); + string fileVersionFolder = Path.Combine(_versionFolder, file); + + if (File.Exists(fileVersionFolder)) + { + if (Utility.MD5Hash.FromFile(fileModFolder) == Utility.MD5Hash.FromFile(fileVersionFolder)) + continue; + } + + string? directory = Path.GetDirectoryName(fileVersionFolder); + + if (directory is null) + continue; + + Directory.CreateDirectory(directory); + + File.Copy(fileModFolder, fileVersionFolder, true); + File.SetAttributes(fileVersionFolder, File.GetAttributes(fileModFolder) & ~FileAttributes.ReadOnly); + } + + // the manifest is primarily here to keep track of what files have been + // deleted from the modifications folder, so that we know when to restore the original files from the downloaded packages + // now check for files that have been deleted from the mod folder according to the manifest + foreach (string fileLocation in App.State.Prop.ModManifest) + { + if (modFolderFiles.Contains(fileLocation)) + continue; + + KeyValuePair packageDirectory; + + try + { + packageDirectory = PackageDirectories.First(x => x.Value != "" && fileLocation.StartsWith(x.Value)); + } + catch (InvalidOperationException) + { + // package doesn't exist, likely mistakenly placed file + string versionFileLocation = Path.Combine(_versionFolder, fileLocation); + + if (File.Exists(versionFileLocation)) + File.Delete(versionFileLocation); + + continue; + } + + // restore original file + string fileName = fileLocation.Substring(packageDirectory.Value.Length); + ExtractFileFromPackage(packageDirectory.Key, fileName); + } + + App.State.Prop.ModManifest = modFolderFiles; + App.State.Save(); + } + + private static async Task CheckModPreset(bool condition, string location, string name) + { + string modFolderLocation = Path.Combine(Directories.Modifications, location); + byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); + + if (condition) + { + if (!File.Exists(modFolderLocation)) + { + string? directory = Path.GetDirectoryName(modFolderLocation); + + if (directory is null) + return; + + Directory.CreateDirectory(directory); + + await File.WriteAllBytesAsync(modFolderLocation, binaryData); + } + } + else if (File.Exists(modFolderLocation) && Utility.MD5Hash.FromFile(modFolderLocation) == Utility.MD5Hash.FromBytes(binaryData)) + { + File.Delete(modFolderLocation); + } + } + + private async Task DownloadPackage(Package package) + { + if (_cancelFired) + return; + + string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}"); + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string robloxPackageLocation = Path.Combine(Directories.LocalAppData, "Roblox", "Downloads", package.Signature); + + if (File.Exists(packageLocation)) + { + FileInfo file = new(packageLocation); + + string calculatedMD5 = Utility.MD5Hash.FromFile(packageLocation); + + if (calculatedMD5 != package.Signature) + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); + file.Delete(); + } + else + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); + _totalDownloadedBytes += package.PackedSize; + UpdateProgressbar(); + return; + } + } + else if (File.Exists(robloxPackageLocation)) + { + // let's cheat! if the stock bootstrapper already previously downloaded the file, + // then we can just copy the one from there + + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); + File.Copy(robloxPackageLocation, packageLocation); + _totalDownloadedBytes += package.PackedSize; + UpdateProgressbar(); + return; + } + + if (!File.Exists(packageLocation)) + { + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); + + { + var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); + var buffer = new byte[4096]; + + await using var stream = await response.Content.ReadAsStreamAsync(_cancelTokenSource.Token); + await using var fileStream = new FileStream(packageLocation, FileMode.CreateNew, FileAccess.Write, FileShare.Delete); + + while (true) + { + if (_cancelFired) + { + stream.Close(); + fileStream.Close(); + return; + } + + var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _cancelTokenSource.Token); + + if (bytesRead == 0) + break; // we're done + + await fileStream.WriteAsync(buffer, 0, bytesRead, _cancelTokenSource.Token); + + _totalDownloadedBytes += bytesRead; + UpdateProgressbar(); + } + } + + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); + } + } + + private async Task ExtractPackage(Package package) + { + if (_cancelFired) + return; + + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); + string extractPath; + + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); + + using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) + { + foreach (ZipArchiveEntry entry in archive.Entries) + { + if (_cancelFired) + return; + + if (entry.FullName.EndsWith('\\')) + continue; + + extractPath = Path.Combine(packageFolder, entry.FullName); + + //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); + + string? directory = Path.GetDirectoryName(extractPath); + + if (directory is null) + continue; + + Directory.CreateDirectory(directory); + + await Task.Run(() => entry.ExtractToFile(extractPath, true)); + } + } + + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); + + _packagesExtracted += 1; + } + + private void ExtractFileFromPackage(string packageName, string fileName) + { + Package? package = _versionPackageManifest.Find(x => x.Name == packageName); + + if (package is null) + return; + + DownloadPackage(package).GetAwaiter().GetResult(); + + string packageLocation = Path.Combine(Directories.Downloads, package.Signature); + string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); + + using ZipArchive archive = ZipFile.OpenRead(packageLocation); + + ZipArchiveEntry? entry = archive.Entries.FirstOrDefault(x => x.FullName == fileName); + + if (entry is null) + return; + + string fileLocation = Path.Combine(packageFolder, entry.FullName); + + File.Delete(fileLocation); + + entry.ExtractToFile(fileLocation); + } + #endregion + } +} From 2258000a89ee8aa565f71f7d076622b3ffbdf3b2 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Tue, 27 Jun 2023 23:57:57 +0100 Subject: [PATCH 066/178] Add build metadata for diagnostics, update checks is this actually gonna work? uhhhh maybe idk --- .github/workflows/ci.yml | 15 +++++--- Bloxstrap/App.xaml.cs | 7 ++++ Bloxstrap/Bloxstrap.csproj | 9 +++++ Bloxstrap/Bootstrapper.cs | 19 +++++++--- Bloxstrap/Extensions/DateTimeEx.cs | 12 +++++++ Bloxstrap/Logger.cs | 4 +-- .../Attributes/CompileTimeInfoAttribute.cs | 21 +++++++++++ .../UI/Menu/ViewModels/AboutViewModel.cs | 16 ++++++++- .../Menu/ViewModels/InstallationViewModel.cs | 3 +- Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml | 35 +++++++++++++++++++ Bloxstrap/Updater.cs | 4 +-- Bloxstrap/Utilities.cs | 7 ++++ 12 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 Bloxstrap/Extensions/DateTimeEx.cs create mode 100644 Bloxstrap/Models/Attributes/CompileTimeInfoAttribute.cs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1921310c..294c81f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,28 +6,33 @@ jobs: strategy: matrix: configuration: [Debug, Release] - platform: [x64] + runs-on: windows-latest steps: - uses: actions/checkout@v3 with: submodules: true + - uses: actions/setup-dotnet@v3 with: dotnet-version: '6.x' + - name: Restore dependencies run: dotnet restore + - name: Build run: dotnet build --no-restore + - name: Publish - run: dotnet publish -p:PublishSingleFile=true -r win-${{ matrix.platform }} -c ${{ matrix.configuration }} --self-contained false .\Bloxstrap\Bloxstrap.csproj + run: dotnet publish -p:PublishSingleFile=true -p:CommitHash=${{ github.sha }} -p:CommitRef=${{ github.ref_type }}/${{ github.ref_name }} -r win-x64 -c ${{ matrix.configuration }} --self-contained false .\Bloxstrap\Bloxstrap.csproj + - name: Upload Artifact uses: actions/upload-artifact@v3 with: - name: Bloxstrap (${{ matrix.configuration }}, ${{ matrix.platform }}) + name: Bloxstrap (${{ matrix.configuration }}, x64) path: | - .\Bloxstrap\bin\${{ matrix.configuration }}\net6.0-windows\win-${{ matrix.platform }}\publish\* + .\Bloxstrap\bin\${{ matrix.configuration }}\net6.0-windows\win-x64\publish\* release: needs: build @@ -40,9 +45,11 @@ jobs: with: name: Bloxstrap (Release, x64) path: x64 + - name: Rename binaries run: | mv x64/Bloxstrap.exe Bloxstrap-${{ github.ref_name }}-x64.exe + - name: Release uses: softprops/action-gh-release@v1 with: diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index d2c1cd0e..1b5a504b 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -15,6 +15,7 @@ using Bloxstrap.Extensions; using Bloxstrap.Models; +using Bloxstrap.Models.Attributes; using Bloxstrap.UI.BootstrapperDialogs; using Bloxstrap.UI.Menu.Views; using Bloxstrap.Utility; @@ -44,6 +45,7 @@ public partial class App : Application public static bool IsMenuLaunch { get; private set; } = false; public static string[] LaunchArgs { get; private set; } = null!; + public static BuildMetadataAttribute BuildMetadata => Assembly.GetExecutingAssembly().GetCustomAttribute()!; public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; // singletons @@ -118,6 +120,11 @@ protected override void OnStartup(StartupEventArgs e) Logger.WriteLine($"[App::OnStartup] Starting {ProjectName} v{Version}"); + if (String.IsNullOrEmpty(BuildMetadata.CommitHash)) + Logger.WriteLine($"[App::OnStartup] Compiled {BuildMetadata.Timestamp.ToFriendlyString()} from {BuildMetadata.Machine}"); + else + Logger.WriteLine($"[App::OnStartup] Compiled {BuildMetadata.Timestamp.ToFriendlyString()} from commit {BuildMetadata.CommitHash} ({BuildMetadata.CommitRef})"); + // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 24f4203b..c4cccd69 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -39,4 +39,13 @@ + + + <_Parameter1>$([System.DateTime]::UtcNow.ToString("s"))Z + <_Parameter2>$(COMPUTERNAME)\$(USERNAME) + <_Parameter3>$(CommitHash) + <_Parameter4>$(CommitRef) + + + diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 5c17080c..2676e9cc 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -576,25 +576,34 @@ private async Task CheckForUpdates() return; } - string currentVersion = $"{App.ProjectName} v{App.Version}"; - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); - if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) + if (releaseInfo is null || releaseInfo.Assets is null) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); + return; + } + + int numCurrentVersion = Utilities.VersionToNumber(App.Version); + int numLatestVersion = Utilities.VersionToNumber(releaseInfo.TagName); + + // check if we aren't using a deployed build, so we can update to one if a new version comes out + if (numCurrentVersion == numLatestVersion && App.BuildMetadata.CommitRef.StartsWith("tag") || numCurrentVersion > numLatestVersion) { App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); return; } + SetStatus($"Getting the latest {App.ProjectName}..."); // 64-bit is always the first option GithubReleaseAsset asset = releaseInfo.Assets[0]; string downloadLocation = Path.Combine(Directories.LocalAppData, "Temp", asset.Name); - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.TagName}..."); if (!File.Exists(downloadLocation)) { @@ -604,7 +613,7 @@ private async Task CheckForUpdates() await response.Content.CopyToAsync(fileStream); } - App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.TagName}..."); ProcessStartInfo startInfo = new() { diff --git a/Bloxstrap/Extensions/DateTimeEx.cs b/Bloxstrap/Extensions/DateTimeEx.cs new file mode 100644 index 00000000..f30d0115 --- /dev/null +++ b/Bloxstrap/Extensions/DateTimeEx.cs @@ -0,0 +1,12 @@ +using System; + +namespace Bloxstrap.Extensions +{ + static class DateTimeEx + { + public static string ToFriendlyString(this DateTime dateTime) + { + return dateTime.ToString("dddd, d MMMM yyyy 'at' h:mm:ss tt", App.CultureFormat); + } + } +} diff --git a/Bloxstrap/Logger.cs b/Bloxstrap/Logger.cs index ad4bc935..883dac25 100644 --- a/Bloxstrap/Logger.cs +++ b/Bloxstrap/Logger.cs @@ -39,9 +39,9 @@ public void Initialize(string filename) public void WriteLine(string message) { - string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'"); + string timestamp = DateTime.UtcNow.ToString("s") + "Z"; string outcon = $"{timestamp} {message}"; - string outlog = outcon.Replace(Directories.UserProfile, ""); + string outlog = outcon.Replace(Directories.UserProfile, "%UserProfile%"); Debug.WriteLine(outcon); WriteToLog(outlog); diff --git a/Bloxstrap/Models/Attributes/CompileTimeInfoAttribute.cs b/Bloxstrap/Models/Attributes/CompileTimeInfoAttribute.cs new file mode 100644 index 00000000..32423f38 --- /dev/null +++ b/Bloxstrap/Models/Attributes/CompileTimeInfoAttribute.cs @@ -0,0 +1,21 @@ +using System; + +namespace Bloxstrap.Models.Attributes +{ + [AttributeUsage(AttributeTargets.Assembly)] + public class BuildMetadataAttribute : Attribute + { + public DateTime Timestamp { get; set; } + public string Machine { get; set; } + public string CommitHash { get; set; } + public string CommitRef { get; set; } + + public BuildMetadataAttribute(string timestamp, string machine, string commitHash, string commitRef) + { + Timestamp = DateTime.Parse(timestamp).ToLocalTime(); + Machine = machine; + CommitHash = commitHash; + CommitRef = commitRef; + } + } +} diff --git a/Bloxstrap/UI/Menu/ViewModels/AboutViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/AboutViewModel.cs index 89566dc5..cea0d437 100644 --- a/Bloxstrap/UI/Menu/ViewModels/AboutViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/AboutViewModel.cs @@ -1,7 +1,21 @@ -namespace Bloxstrap.UI.Menu.ViewModels +using System; +using System.Windows; + +using Bloxstrap.Extensions; +using Bloxstrap.Models.Attributes; + +namespace Bloxstrap.UI.Menu.ViewModels { public class AboutViewModel { public string Version => $"Version {App.Version}"; + + public BuildMetadataAttribute BuildMetadata => App.BuildMetadata; + + public string BuildTimestamp => BuildMetadata.Timestamp.ToFriendlyString(); + public string BuildCommitHashUrl => $"https://github.com/{App.ProjectRepository}/commit/{BuildMetadata.CommitHash}"; + + public Visibility BuildInformationVisibility => BuildMetadata.CommitRef.StartsWith("tag") ? Visibility.Collapsed : Visibility.Visible; + public Visibility BuildCommitVisibility => String.IsNullOrEmpty(BuildMetadata.CommitHash) ? Visibility.Collapsed : Visibility.Visible; } } diff --git a/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs index e3ca027c..cfd75b57 100644 --- a/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs @@ -12,6 +12,7 @@ using CommunityToolkit.Mvvm.Input; using Bloxstrap.Enums; +using Bloxstrap.Extensions; using Bloxstrap.Models; namespace Bloxstrap.UI.Menu.ViewModels @@ -50,7 +51,7 @@ private async Task LoadChannelDeployInfo(string channel) { Version = info.Version, VersionGuid = info.VersionGuid, - Timestamp = info.Timestamp?.ToString("dddd, d MMMM yyyy 'at' h:mm:ss tt", App.CultureFormat)! + Timestamp = info.Timestamp?.ToFriendlyString()! }; OnPropertyChanged(nameof(ChannelDeployInfo)); diff --git a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml index 2a6f0bc7..e2a3d096 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml @@ -41,6 +41,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Bloxstrap/Updater.cs b/Bloxstrap/Updater.cs index d229f1c7..e9d53a4c 100644 --- a/Bloxstrap/Updater.cs +++ b/Bloxstrap/Updater.cs @@ -19,11 +19,9 @@ public static void CheckInstalledVersion() // 2.0.0 downloads updates to /Updates so lol bool isAutoUpgrade = Environment.ProcessPath.StartsWith(Path.Combine(Directories.Base, "Updates")) || Environment.ProcessPath.StartsWith(Path.Combine(Directories.LocalAppData, "Temp")); - // if downloaded version doesn't match, replace installed version with downloaded version FileVersionInfo currentVersionInfo = FileVersionInfo.GetVersionInfo(Environment.ProcessPath); - FileVersionInfo installedVersionInfo = FileVersionInfo.GetVersionInfo(Directories.Application); - if (installedVersionInfo.ProductVersion == currentVersionInfo.ProductVersion) + if (Utility.MD5Hash.FromFile(Environment.ProcessPath) == Utility.MD5Hash.FromFile(Directories.Application)) return; MessageBoxResult result; diff --git a/Bloxstrap/Utilities.cs b/Bloxstrap/Utilities.cs index 53571d90..43711464 100644 --- a/Bloxstrap/Utilities.cs +++ b/Bloxstrap/Utilities.cs @@ -39,5 +39,12 @@ public static long GetFreeDiskSpace(string path) return default; } } + + public static int VersionToNumber(string version) + { + // yes this is kinda stupid lol + version = version.Replace("v", "").Replace(".", ""); + return Int32.Parse(version); + } } } From 3a77746daa1a97c961d36444af1a81a034e3f676 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 28 Jun 2023 00:08:25 +0100 Subject: [PATCH 067/178] Remove reference for IniParser --- Bloxstrap/Bloxstrap.csproj | 1 - Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index c4cccd69..ddc7eaa2 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -31,7 +31,6 @@ - diff --git a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml index e2a3d096..1f398d89 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml @@ -183,9 +183,9 @@ - + - + @@ -195,14 +195,6 @@ - - - - - - - - From fe885cb24be496e1ee1f4ab1951ef02c57b27a00 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 28 Jun 2023 00:08:57 +0100 Subject: [PATCH 068/178] Bump version number --- Bloxstrap/Bloxstrap.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index ddc7eaa2..c2e0c579 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -7,8 +7,8 @@ true True Bloxstrap.ico - 2.3.0 - 2.3.0.0 + 2.4.0 + 2.4.0.0 app.manifest From 991005c6a702506b86fa47990987ea6bc7d1788e Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 28 Jun 2023 20:57:23 +0100 Subject: [PATCH 069/178] Improve channel input selection handling input value is now trimmed, as well as input being processed on enter --- .../Menu/ViewModels/InstallationViewModel.cs | 6 ++--- .../UI/Menu/Views/Pages/InstallationPage.xaml | 2 +- .../Menu/Views/Pages/InstallationPage.xaml.cs | 23 ++++++++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs index cfd75b57..3b5c0205 100644 --- a/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/InstallationViewModel.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading.Tasks; using System.Windows; -using System.Windows.Forms; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; @@ -65,9 +64,9 @@ private async Task LoadChannelDeployInfo(string channel) private void BrowseInstallLocation() { - using var dialog = new FolderBrowserDialog(); + using var dialog = new System.Windows.Forms.FolderBrowserDialog(); - if (dialog.ShowDialog() != DialogResult.OK) + if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; if (!dialog.SelectedPath.EndsWith(App.ProjectName)) @@ -96,6 +95,7 @@ public string Channel get => App.Settings.Prop.Channel; set { + value = value.Trim(); Task.Run(() => LoadChannelDeployInfo(value)); App.Settings.Prop.Channel = value; } diff --git a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml index 81a9bac1..dbce9db3 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml @@ -59,7 +59,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml.cs b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml.cs index 19c7d32f..84d03e5e 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml.cs +++ b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml.cs @@ -1,4 +1,9 @@ -using Bloxstrap.UI.Menu.ViewModels; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; + +using Bloxstrap.UI.Menu.ViewModels; namespace Bloxstrap.UI.Menu.Views.Pages { @@ -12,5 +17,21 @@ public InstallationPage() DataContext = new InstallationViewModel(); InitializeComponent(); } + + // https://stackoverflow.com/a/13289118/11852173 + // yes this doesnt fully conform to xaml but whatever + private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + TextBox tBox = (TextBox)sender; + DependencyProperty prop = TextBox.TextProperty; + + BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop); + + if (binding is not null) + binding.UpdateSource(); + } + } } } From d27ca05c32e6560b95c7e9893dfbbd5b67df3592 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 28 Jun 2023 21:42:50 +0100 Subject: [PATCH 070/178] Move altered padding to wpfui --- Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml | 10 +++++----- .../UI/Menu/Views/Pages/AppearancePage.xaml | 8 ++++---- .../UI/Menu/Views/Pages/BehaviourPage.xaml | 4 ++-- .../UI/Menu/Views/Pages/FastFlagsPage.xaml | 16 ++++++++-------- .../UI/Menu/Views/Pages/InstallationPage.xaml | 8 ++++---- .../UI/Menu/Views/Pages/IntegrationsPage.xaml | 8 ++++---- Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml | 18 ++++++++++-------- wpfui | 2 +- 8 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml index 1f398d89..afd2b749 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/AboutPage.xaml @@ -165,31 +165,31 @@ - + - + - + - + - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml b/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml index b5b2c4ca..48e9be1f 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/AppearancePage.xaml @@ -12,7 +12,7 @@ - + @@ -21,7 +21,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -50,7 +50,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml index e0d7ff41..190a5391 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/BehaviourPage.xaml @@ -11,7 +11,7 @@ - + @@ -20,7 +20,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml index d7a130e3..6d69573d 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/FastFlagsPage.xaml @@ -12,7 +12,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -60,7 +60,7 @@ - + @@ -69,7 +69,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -98,7 +98,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml index dbce9db3..99cb18d2 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/InstallationPage.xaml @@ -12,7 +12,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -121,7 +121,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml index 234dfd0e..db022b2f 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/IntegrationsPage.xaml @@ -13,7 +13,7 @@ - + @@ -22,7 +22,7 @@ - + @@ -33,7 +33,7 @@ - + @@ -42,7 +42,7 @@ - + diff --git a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml index 7c801c4f..4b66f38b 100644 --- a/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Menu/Views/Pages/ModsPage.xaml @@ -21,7 +21,7 @@ - + @@ -35,12 +35,14 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs index f423e1b9..a1627f73 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs @@ -1,4 +1,9 @@ -using Bloxstrap.UI.ViewModels.Menu; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; + +using Bloxstrap.UI.ViewModels.Menu; namespace Bloxstrap.UI.Menu.Pages { @@ -12,5 +17,21 @@ public BehaviourPage() DataContext = new BehaviourViewModel(); InitializeComponent(); } + + // https://stackoverflow.com/a/13289118/11852173 + // yes this doesnt fully conform to xaml but whatever + private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + TextBox tBox = (TextBox)sender; + DependencyProperty prop = TextBox.TextProperty; + + BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop); + + if (binding is not null) + binding.UpdateSource(); + } + } } } diff --git a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml index 510f8a89..b478e7b5 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml @@ -10,7 +10,7 @@ Title="InstallationPage" Scrollable="True"> - + @@ -46,89 +46,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml.cs index 7bf5b8b1..1a21b6d8 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml.cs @@ -1,9 +1,4 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Input; - -using Bloxstrap.UI.ViewModels.Menu; +using Bloxstrap.UI.ViewModels.Menu; namespace Bloxstrap.UI.Menu.Pages { @@ -17,21 +12,5 @@ public InstallationPage() DataContext = new InstallationViewModel(); InitializeComponent(); } - - // https://stackoverflow.com/a/13289118/11852173 - // yes this doesnt fully conform to xaml but whatever - private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - { - TextBox tBox = (TextBox)sender; - DependencyProperty prop = TextBox.TextProperty; - - BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop); - - if (binding is not null) - binding.UpdateSource(); - } - } } } diff --git a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs index d5fb0426..78661f31 100644 --- a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs @@ -1,7 +1,60 @@ -namespace Bloxstrap.UI.ViewModels.Menu +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + + +using Bloxstrap.Enums; +using Bloxstrap.Extensions; +using Bloxstrap.Models; + +namespace Bloxstrap.UI.ViewModels.Menu { - public class BehaviourViewModel + public class BehaviourViewModel : INotifyPropertyChanged { + public event PropertyChangedEventHandler? PropertyChanged; + public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + private bool _manualChannelEntry = !RobloxDeployment.SelectableChannels.Contains(App.Settings.Prop.Channel); + + public BehaviourViewModel() + { + Task.Run(() => LoadChannelDeployInfo(App.Settings.Prop.Channel)); + } + + private async Task LoadChannelDeployInfo(string channel) + { + ChannelInfoLoadingText = "Fetching latest deploy info, please wait..."; + OnPropertyChanged(nameof(ChannelInfoLoadingText)); + + ChannelDeployInfo = null; + OnPropertyChanged(nameof(ChannelDeployInfo)); + + try + { + ClientVersion info = await RobloxDeployment.GetInfo(channel, true); + + ChannelDeployInfo = new DeployInfo + { + Version = info.Version, + VersionGuid = info.VersionGuid, + Timestamp = info.Timestamp?.ToFriendlyString()! + }; + + OnPropertyChanged(nameof(ChannelDeployInfo)); + } + catch (Exception) + { + ChannelInfoLoadingText = "Failed to get deploy info.\nIs the channel name valid?"; + OnPropertyChanged(nameof(ChannelInfoLoadingText)); + } + } + + public DeployInfo? ChannelDeployInfo { get; private set; } = null; + public string ChannelInfoLoadingText { get; private set; } = null!; + public bool CreateDesktopIcon { get => App.Settings.Prop.CreateDesktopIcon; @@ -13,5 +66,56 @@ public bool UpdateCheckingEnabled get => App.Settings.Prop.CheckForUpdates; set => App.Settings.Prop.CheckForUpdates = value; } + + public IEnumerable Channels => RobloxDeployment.SelectableChannels; + + public string Channel + { + get => App.Settings.Prop.Channel; + set + { + value = value.Trim(); + Task.Run(() => LoadChannelDeployInfo(value)); + App.Settings.Prop.Channel = value; + } + } + + public bool ManualChannelEntry + { + get => _manualChannelEntry; + set + { + _manualChannelEntry = value; + + if (!value) + { + // roblox typically sets channels in all lowercase, so here we find if a case insensitive match exists + string? matchingChannel = Channels.Where(x => x.ToLowerInvariant() == Channel.ToLowerInvariant()).FirstOrDefault(); + Channel = string.IsNullOrEmpty(matchingChannel) ? RobloxDeployment.DefaultChannel : matchingChannel; + } + + OnPropertyChanged(nameof(Channel)); + OnPropertyChanged(nameof(ChannelComboBoxVisibility)); + OnPropertyChanged(nameof(ChannelTextBoxVisibility)); + } + } + + // cant use data bindings so i have to do whatever tf this is + public Visibility ChannelComboBoxVisibility => ManualChannelEntry ? Visibility.Collapsed : Visibility.Visible; + public Visibility ChannelTextBoxVisibility => ManualChannelEntry ? Visibility.Visible : Visibility.Collapsed; + + // todo - move to enum attributes? + public IReadOnlyDictionary ChannelChangeModes => new Dictionary + { + { "Change automatically", ChannelChangeMode.Automatic }, + { "Always prompt", ChannelChangeMode.Prompt }, + { "Never change", ChannelChangeMode.Ignore }, + }; + + public string SelectedChannelChangeMode + { + get => ChannelChangeModes.FirstOrDefault(x => x.Value == App.Settings.Prop.ChannelChangeMode).Key; + set => App.Settings.Prop.ChannelChangeMode = ChannelChangeModes[value]; + } } } diff --git a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs index 43d33eb0..5a659f73 100644 --- a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs @@ -1,19 +1,9 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; +using System.ComponentModel; using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; -using Bloxstrap.Models; - namespace Bloxstrap.UI.ViewModels.Menu { public class InstallationViewModel : INotifyPropertyChanged @@ -21,47 +11,9 @@ public class InstallationViewModel : INotifyPropertyChanged public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private bool _manualChannelEntry = !RobloxDeployment.SelectableChannels.Contains(App.Settings.Prop.Channel); - public ICommand BrowseInstallLocationCommand => new RelayCommand(BrowseInstallLocation); public ICommand OpenFolderCommand => new RelayCommand(OpenFolder); - public DeployInfo? ChannelDeployInfo { get; private set; } = null; - public string ChannelInfoLoadingText { get; private set; } = null!; - - public InstallationViewModel() - { - Task.Run(() => LoadChannelDeployInfo(App.Settings.Prop.Channel)); - } - - private async Task LoadChannelDeployInfo(string channel) - { - ChannelInfoLoadingText = "Fetching latest deploy info, please wait..."; - OnPropertyChanged(nameof(ChannelInfoLoadingText)); - - ChannelDeployInfo = null; - OnPropertyChanged(nameof(ChannelDeployInfo)); - - try - { - ClientVersion info = await RobloxDeployment.GetInfo(channel, true); - - ChannelDeployInfo = new DeployInfo - { - Version = info.Version, - VersionGuid = info.VersionGuid, - Timestamp = info.Timestamp?.ToFriendlyString()! - }; - - OnPropertyChanged(nameof(ChannelDeployInfo)); - } - catch (Exception) - { - ChannelInfoLoadingText = "Failed to get deploy info.\nIs the channel name valid?"; - OnPropertyChanged(nameof(ChannelInfoLoadingText)); - } - } - private void BrowseInstallLocation() { using var dialog = new System.Windows.Forms.FolderBrowserDialog(); @@ -84,56 +36,5 @@ public string InstallLocation get => App.BaseDirectory; set => App.BaseDirectory = value; } - - public IEnumerable Channels => RobloxDeployment.SelectableChannels; - - public string Channel - { - get => App.Settings.Prop.Channel; - set - { - value = value.Trim(); - Task.Run(() => LoadChannelDeployInfo(value)); - App.Settings.Prop.Channel = value; - } - } - - public bool ManualChannelEntry - { - get => _manualChannelEntry; - set - { - _manualChannelEntry = value; - - if (!value) - { - // roblox typically sets channels in all lowercase, so here we find if a case insensitive match exists - string? matchingChannel = Channels.Where(x => x.ToLowerInvariant() == Channel.ToLowerInvariant()).FirstOrDefault(); - Channel = string.IsNullOrEmpty(matchingChannel) ? RobloxDeployment.DefaultChannel : matchingChannel; - } - - OnPropertyChanged(nameof(Channel)); - OnPropertyChanged(nameof(ChannelComboBoxVisibility)); - OnPropertyChanged(nameof(ChannelTextBoxVisibility)); - } - } - - // cant use data bindings so i have to do whatever tf this is - public Visibility ChannelComboBoxVisibility => ManualChannelEntry ? Visibility.Collapsed : Visibility.Visible; - public Visibility ChannelTextBoxVisibility => ManualChannelEntry ? Visibility.Visible : Visibility.Collapsed; - - // todo - move to enum attributes? - public IReadOnlyDictionary ChannelChangeModes => new Dictionary - { - { "Change automatically", ChannelChangeMode.Automatic }, - { "Always prompt", ChannelChangeMode.Prompt }, - { "Never change", ChannelChangeMode.Ignore }, - }; - - public string SelectedChannelChangeMode - { - get => ChannelChangeModes.FirstOrDefault(x => x.Value == App.Settings.Prop.ChannelChangeMode).Key; - set => App.Settings.Prop.ChannelChangeMode = ChannelChangeModes[value]; - } } } From 054379d4f0faf57d1c144a1ee6a711fc37fc80c0 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 13 Jul 2023 13:15:03 +0100 Subject: [PATCH 083/178] Channel selection - editable textbox, error icon --- .../UI/Elements/Menu/Pages/BehaviourPage.xaml | 94 +++++++++---------- .../Elements/Menu/Pages/BehaviourPage.xaml.cs | 8 +- .../UI/ViewModels/Menu/BehaviourViewModel.cs | 36 ++++--- 3 files changed, 70 insertions(+), 68 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml index 61d4049c..0c193c2d 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml @@ -42,66 +42,58 @@ - - + - + + + + + + + + + - + - - - - - - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs index a1627f73..db864e10 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs @@ -20,14 +20,14 @@ public BehaviourPage() // https://stackoverflow.com/a/13289118/11852173 // yes this doesnt fully conform to xaml but whatever - private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e) + private void ComboBox_KeyEnterUpdate(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { - TextBox tBox = (TextBox)sender; - DependencyProperty prop = TextBox.TextProperty; + ComboBox box = (ComboBox)sender; + DependencyProperty prop = ComboBox.TextProperty; - BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop); + BindingExpression binding = BindingOperations.GetBindingExpression(box, prop); if (binding is not null) binding.UpdateSource(); diff --git a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs index 78661f31..6c19562c 100644 --- a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs @@ -26,10 +26,14 @@ public BehaviourViewModel() private async Task LoadChannelDeployInfo(string channel) { + LoadingSpinnerVisibility = Visibility.Visible; + LoadingErrorVisibility = Visibility.Collapsed; ChannelInfoLoadingText = "Fetching latest deploy info, please wait..."; - OnPropertyChanged(nameof(ChannelInfoLoadingText)); - ChannelDeployInfo = null; + + OnPropertyChanged(nameof(LoadingSpinnerVisibility)); + OnPropertyChanged(nameof(LoadingErrorVisibility)); + OnPropertyChanged(nameof(ChannelInfoLoadingText)); OnPropertyChanged(nameof(ChannelDeployInfo)); try @@ -47,11 +51,19 @@ private async Task LoadChannelDeployInfo(string channel) } catch (Exception) { - ChannelInfoLoadingText = "Failed to get deploy info.\nIs the channel name valid?"; + LoadingSpinnerVisibility = Visibility.Collapsed; + LoadingErrorVisibility = Visibility.Visible; + ChannelInfoLoadingText = "Could not get deployment information. Is the channel name valid?"; + + OnPropertyChanged(nameof(LoadingSpinnerVisibility)); + OnPropertyChanged(nameof(LoadingErrorVisibility)); OnPropertyChanged(nameof(ChannelInfoLoadingText)); } } + public Visibility LoadingSpinnerVisibility { get; private set; } = Visibility.Visible; + public Visibility LoadingErrorVisibility { get; private set; } = Visibility.Collapsed; + public DeployInfo? ChannelDeployInfo { get; private set; } = null; public string ChannelInfoLoadingText { get; private set; } = null!; @@ -69,12 +81,16 @@ public bool UpdateCheckingEnabled public IEnumerable Channels => RobloxDeployment.SelectableChannels; - public string Channel + public string SelectedChannel { get => App.Settings.Prop.Channel; set { value = value.Trim(); + + if (String.IsNullOrEmpty(value)) + value = RobloxDeployment.DefaultChannel; + Task.Run(() => LoadChannelDeployInfo(value)); App.Settings.Prop.Channel = value; } @@ -90,20 +106,14 @@ public bool ManualChannelEntry if (!value) { // roblox typically sets channels in all lowercase, so here we find if a case insensitive match exists - string? matchingChannel = Channels.Where(x => x.ToLowerInvariant() == Channel.ToLowerInvariant()).FirstOrDefault(); - Channel = string.IsNullOrEmpty(matchingChannel) ? RobloxDeployment.DefaultChannel : matchingChannel; + string? matchingChannel = Channels.Where(x => x.ToLowerInvariant() == SelectedChannel.ToLowerInvariant()).FirstOrDefault(); + SelectedChannel = string.IsNullOrEmpty(matchingChannel) ? RobloxDeployment.DefaultChannel : matchingChannel; } - OnPropertyChanged(nameof(Channel)); - OnPropertyChanged(nameof(ChannelComboBoxVisibility)); - OnPropertyChanged(nameof(ChannelTextBoxVisibility)); + OnPropertyChanged(nameof(SelectedChannel)); } } - // cant use data bindings so i have to do whatever tf this is - public Visibility ChannelComboBoxVisibility => ManualChannelEntry ? Visibility.Collapsed : Visibility.Visible; - public Visibility ChannelTextBoxVisibility => ManualChannelEntry ? Visibility.Visible : Visibility.Collapsed; - // todo - move to enum attributes? public IReadOnlyDictionary ChannelChangeModes => new Dictionary { From e683af373d2407bf8ddc4255132c4a7bf2edae22 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 13 Jul 2023 13:29:27 +0100 Subject: [PATCH 084/178] Channel selector - warning if out of date --- Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml | 7 +++++++ Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml index 0c193c2d..9f28d66b 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml @@ -61,6 +61,7 @@ + @@ -75,6 +76,11 @@ + + + + + @@ -93,6 +99,7 @@ + diff --git a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs index 6c19562c..331c9974 100644 --- a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs @@ -40,6 +40,11 @@ private async Task LoadChannelDeployInfo(string channel) { ClientVersion info = await RobloxDeployment.GetInfo(channel, true); + if (info.Timestamp?.AddMonths(1) < DateTime.Now) + ChannelWarningVisibility = Visibility.Visible; + else + ChannelWarningVisibility = Visibility.Collapsed; + ChannelDeployInfo = new DeployInfo { Version = info.Version, @@ -47,13 +52,14 @@ private async Task LoadChannelDeployInfo(string channel) Timestamp = info.Timestamp?.ToFriendlyString()! }; + OnPropertyChanged(nameof(ChannelWarningVisibility)); OnPropertyChanged(nameof(ChannelDeployInfo)); } catch (Exception) { LoadingSpinnerVisibility = Visibility.Collapsed; LoadingErrorVisibility = Visibility.Visible; - ChannelInfoLoadingText = "Could not get deployment information. Is the channel name valid?"; + ChannelInfoLoadingText = "Could not get deployment information! Is the channel name valid?"; OnPropertyChanged(nameof(LoadingSpinnerVisibility)); OnPropertyChanged(nameof(LoadingErrorVisibility)); @@ -63,6 +69,7 @@ private async Task LoadChannelDeployInfo(string channel) public Visibility LoadingSpinnerVisibility { get; private set; } = Visibility.Visible; public Visibility LoadingErrorVisibility { get; private set; } = Visibility.Collapsed; + public Visibility ChannelWarningVisibility { get; private set; } = Visibility.Collapsed; public DeployInfo? ChannelDeployInfo { get; private set; } = null; public string ChannelInfoLoadingText { get; private set; } = null!; From 88ea69c56d57d037ef23ab3eeca388d207a74652 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Fri, 14 Jul 2023 23:20:58 +0100 Subject: [PATCH 085/178] Rework emoji font mod --- Bloxstrap/Bootstrapper.cs | 21 ++++++++----------- Bloxstrap/Extensions/EmojiTypeEx.cs | 12 ++++++++++- Bloxstrap/Models/Settings.cs | 2 +- Bloxstrap/Models/State.cs | 1 - Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs | 4 ++-- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 9e83cbdb..1f6e4d9a 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1010,27 +1010,24 @@ private async Task ApplyModifications() await CheckModPreset(App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"), @"ExtraContent\places\Mobile.rbxl", ""); // emoji presets are downloaded remotely from github due to how large they are - string emojiFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\TwemojiMozilla.ttf"); + string contentFonts = Path.Combine(Directories.Modifications, "content\\fonts"); + string emojiFontLocation = Path.Combine(contentFonts, "TwemojiMozilla.ttf"); + string emojiFontHash = File.Exists(emojiFontLocation) ? Utility.MD5Hash.FromFile(emojiFontLocation) : ""; - if (App.Settings.Prop.PreferredEmojiType == EmojiType.Default && App.State.Prop.CurrentEmojiType != EmojiType.Default) + if (App.Settings.Prop.EmojiType == EmojiType.Default && EmojiTypeEx.Hashes.Values.Contains(emojiFontHash)) { - if (File.Exists(emojiFontLocation)) - File.Delete(emojiFontLocation); - - App.State.Prop.CurrentEmojiType = EmojiType.Default; + File.Delete(emojiFontLocation); } - else if (App.Settings.Prop.PreferredEmojiType != EmojiType.Default && App.State.Prop.CurrentEmojiType != App.Settings.Prop.PreferredEmojiType) + else if (App.Settings.Prop.EmojiType != EmojiType.Default && emojiFontHash != App.Settings.Prop.EmojiType.GetHash()) { - if (File.Exists(emojiFontLocation)) + if (emojiFontHash != "") File.Delete(emojiFontLocation); - string remoteEmojiLocation = App.Settings.Prop.PreferredEmojiType.GetRemoteLocation(); + Directory.CreateDirectory(contentFonts); - var response = await App.HttpClient.GetAsync(remoteEmojiLocation); + var response = await App.HttpClient.GetAsync(App.Settings.Prop.EmojiType.GetUrl()); await using var fileStream = new FileStream(emojiFontLocation, FileMode.CreateNew); await response.Content.CopyToAsync(fileStream); - - App.State.Prop.CurrentEmojiType = App.Settings.Prop.PreferredEmojiType; } foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) diff --git a/Bloxstrap/Extensions/EmojiTypeEx.cs b/Bloxstrap/Extensions/EmojiTypeEx.cs index 5978b661..07fd220e 100644 --- a/Bloxstrap/Extensions/EmojiTypeEx.cs +++ b/Bloxstrap/Extensions/EmojiTypeEx.cs @@ -23,7 +23,17 @@ static class EmojiTypeEx { EmojiType.Windows8, "Win8.1SegoeUIEmoji.ttf" }, }; - public static string GetRemoteLocation(this EmojiType emojiType) + public static IReadOnlyDictionary Hashes => new Dictionary + { + { EmojiType.Catmoji, "98138f398a8cde897074dd2b8d53eca0" }, + { EmojiType.Windows11, "d50758427673578ddf6c9edcdbf367f5" }, + { EmojiType.Windows10, "d8a7eecbebf9dfdf622db8ccda63aff5" }, + { EmojiType.Windows8, "2b01c6caabbe95afc92aa63b9bf100f3" }, + }; + + public static string GetHash(this EmojiType emojiType) => Hashes[emojiType]; + + public static string GetUrl(this EmojiType emojiType) { if (emojiType == EmojiType.Default) return ""; diff --git a/Bloxstrap/Models/Settings.cs b/Bloxstrap/Models/Settings.cs index 477d324c..80e28c2e 100644 --- a/Bloxstrap/Models/Settings.cs +++ b/Bloxstrap/Models/Settings.cs @@ -31,7 +31,7 @@ public class Settings public bool UseOldCharacterSounds { get; set; } = false; public bool UseOldMouseCursor { get; set; } = false; public bool UseDisableAppPatch { get; set; } = false; - public EmojiType PreferredEmojiType { get; set; } = EmojiType.Default; + public EmojiType EmojiType { get; set; } = EmojiType.Default; public bool DisableFullscreenOptimizations { get; set; } = false; } } diff --git a/Bloxstrap/Models/State.cs b/Bloxstrap/Models/State.cs index cd1a7fcf..b099001e 100644 --- a/Bloxstrap/Models/State.cs +++ b/Bloxstrap/Models/State.cs @@ -7,7 +7,6 @@ namespace Bloxstrap.Models public class State { public string VersionGuid { get; set; } = ""; - public EmojiType CurrentEmojiType { get; set; } = EmojiType.Default; public List ModManifest { get; set; } = new(); } } diff --git a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs index a1b20ca2..1f94b4c7 100644 --- a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs @@ -44,8 +44,8 @@ public bool DisableAppPatchEnabled public string SelectedEmojiType { - get => EmojiTypes.FirstOrDefault(x => x.Value == App.Settings.Prop.PreferredEmojiType).Key; - set => App.Settings.Prop.PreferredEmojiType = EmojiTypes[value]; + get => EmojiTypes.FirstOrDefault(x => x.Value == App.Settings.Prop.EmojiType).Key; + set => App.Settings.Prop.EmojiType = EmojiTypes[value]; } public bool DisableFullscreenOptimizationsEnabled From ade4a893388c968a4e7ea63b1ed0226d43c14cba Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 00:05:49 +0100 Subject: [PATCH 086/178] Add option to use pre-2013 mouse cursor --- Bloxstrap/Bloxstrap.csproj | 8 +- Bloxstrap/Bootstrapper.cs | 37 ++++--- Bloxstrap/Enums/CursorType.cs | 9 ++ Bloxstrap/Extensions/CursorTypeEx.cs | 16 +++ Bloxstrap/Models/Settings.cs | 2 +- .../Mods/Cursor/From2006/ArrowCursor.png | Bin 0 -> 2065 bytes .../Mods/Cursor/From2006/ArrowFarCursor.png | Bin 0 -> 2169 bytes .../From2013/ArrowCursor.png} | Bin .../From2013/ArrowFarCursor.png} | Bin .../UI/Elements/Menu/Pages/ModsPage.xaml | 103 ++++++++---------- Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs | 8 +- 11 files changed, 101 insertions(+), 82 deletions(-) create mode 100644 Bloxstrap/Enums/CursorType.cs create mode 100644 Bloxstrap/Extensions/CursorTypeEx.cs create mode 100644 Bloxstrap/Resources/Mods/Cursor/From2006/ArrowCursor.png create mode 100644 Bloxstrap/Resources/Mods/Cursor/From2006/ArrowFarCursor.png rename Bloxstrap/Resources/Mods/{OldCursor.png => Cursor/From2013/ArrowCursor.png} (100%) rename Bloxstrap/Resources/Mods/{OldFarCursor.png => Cursor/From2013/ArrowFarCursor.png} (100%) diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 11901f0c..f1ce5f15 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -24,10 +24,12 @@ + + + + - - diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 1f6e4d9a..16059f88 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -998,15 +998,20 @@ private async Task ApplyModifications() if (!Directory.Exists(modFolder)) Directory.CreateDirectory(modFolder); - await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "OldCursor.png"); - await CheckModPreset(App.Settings.Prop.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "OldFarCursor.png"); + // cursors + await CheckModPreset(App.Settings.Prop.CursorType != CursorType.Default, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", $"Cursor.{App.Settings.Prop.CursorType}.ArrowCursor.png"); + await CheckModPreset(App.Settings.Prop.CursorType != CursorType.Default, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", $"Cursor.{App.Settings.Prop.CursorType}.ArrowFarCursor.png"); + + // character sounds await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_falling.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump_land.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_swim.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); + await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); + + // misc await CheckModPreset(App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"), @"ExtraContent\places\Mobile.rbxl", ""); // emoji presets are downloaded remotely from github due to how large they are @@ -1104,26 +1109,22 @@ private async Task ApplyModifications() private static async Task CheckModPreset(bool condition, string location, string name) { - string modFolderLocation = Path.Combine(Directories.Modifications, location); - byte[] binaryData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); + string fullLocation = Path.Combine(Directories.Modifications, location); + byte[] embeddedData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); - if (condition) - { - if (!File.Exists(modFolderLocation)) - { - string? directory = Path.GetDirectoryName(modFolderLocation); + string fileHash = File.Exists(fullLocation) ? Utility.MD5Hash.FromFile(fullLocation) : ""; + string embeddedHash = Utility.MD5Hash.FromBytes(embeddedData); - if (directory is null) - return; + if (condition && fileHash != embeddedHash) + { + Directory.CreateDirectory(Path.GetDirectoryName(fullLocation)!); + File.Delete(fullLocation); - Directory.CreateDirectory(directory); - - await File.WriteAllBytesAsync(modFolderLocation, binaryData); - } + await File.WriteAllBytesAsync(fullLocation, embeddedData); } - else if (File.Exists(modFolderLocation) && Utility.MD5Hash.FromFile(modFolderLocation) == Utility.MD5Hash.FromBytes(binaryData)) + else if (!condition && fileHash != "") { - File.Delete(modFolderLocation); + File.Delete(fullLocation); } } diff --git a/Bloxstrap/Enums/CursorType.cs b/Bloxstrap/Enums/CursorType.cs new file mode 100644 index 00000000..98e8ec44 --- /dev/null +++ b/Bloxstrap/Enums/CursorType.cs @@ -0,0 +1,9 @@ +namespace Bloxstrap.Enums +{ + public enum CursorType + { + Default, + From2006, + From2013 + } +} diff --git a/Bloxstrap/Extensions/CursorTypeEx.cs b/Bloxstrap/Extensions/CursorTypeEx.cs new file mode 100644 index 00000000..3afe6926 --- /dev/null +++ b/Bloxstrap/Extensions/CursorTypeEx.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +using Bloxstrap.Enums; + +namespace Bloxstrap.Extensions +{ + static class CursorTypeEx + { + public static IReadOnlyDictionary Selections => new Dictionary + { + { "Default", CursorType.Default }, + { "Before 2022", CursorType.From2013 }, + { "Before 2013", CursorType.From2006 }, + }; + } +} diff --git a/Bloxstrap/Models/Settings.cs b/Bloxstrap/Models/Settings.cs index 80e28c2e..604e3c20 100644 --- a/Bloxstrap/Models/Settings.cs +++ b/Bloxstrap/Models/Settings.cs @@ -29,8 +29,8 @@ public class Settings // mod preset configuration public bool UseOldDeathSound { get; set; } = true; public bool UseOldCharacterSounds { get; set; } = false; - public bool UseOldMouseCursor { get; set; } = false; public bool UseDisableAppPatch { get; set; } = false; + public CursorType CursorType { get; set; } = CursorType.Default; public EmojiType EmojiType { get; set; } = EmojiType.Default; public bool DisableFullscreenOptimizations { get; set; } = false; } diff --git a/Bloxstrap/Resources/Mods/Cursor/From2006/ArrowCursor.png b/Bloxstrap/Resources/Mods/Cursor/From2006/ArrowCursor.png new file mode 100644 index 0000000000000000000000000000000000000000..85c463983a935de602927cec0f490c630091476c GIT binary patch literal 2065 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 literal 0 HcmV?d00001 diff --git a/Bloxstrap/Resources/Mods/Cursor/From2006/ArrowFarCursor.png b/Bloxstrap/Resources/Mods/Cursor/From2006/ArrowFarCursor.png new file mode 100644 index 0000000000000000000000000000000000000000..9a1954a334a7b330ad6beae16d11c14ef670f0a6 GIT binary patch literal 2169 zcmb7F`8yMiA9uDKi_8$JIaY3SPAILAOmY;V^wpp6eLv6Z{d%6)^Ss`#=Xw3|PDa^W0t!kCa&d71krt+Q2aNiM!-o!b z`q7Q*15zWIp-C4*ys;#F;0=faKERvH0T&9<)`r-72SK!9Fg=KtwxKS}PzMfChZ(?N zwQnsJ4}1U;(%K9#!Yw2r!{;Ec>Tw_m1X(x}xwuYr`~!Cv-ogGrSY16@LF+oaSgb4);Jk_6gkjP{!bg|pz%PGOkLPT40bMx1{hYxdyaHQFM zz}&blELQ+}mu^>8B1Kr{@Vm6|;A0*m&VHe0W@2)(vW`lhJZUoY=~HV>X=!)i5RNf1 zKE7go>Yj*KF%?A?201hM8NIJXv>*tL9d1x?x-Atp6Pu!>q9Qoa5HMkzm6f$n+xKvO zHY_a6XZwczs*!Nntr|k0IS^(1xMUrG8z#^vySg4vybSuY`?CU%$9E464K*eSAM12; zbyf3(DsL)MdlU3pp8LwGvP`9ZodpG_1x_(`FwV|nyztmxYct`E{$n9Z%E}ew$)@0K z27{qieYdZmtv#?EP7NX&(cz=)!k2-dUvOn?M;w1NtMclNv(0r)O=O~@ zfNEr9^bm~fOMEe6jsCL{E6DjJh)7&tE+p{lW}q|COW#Q zwY9bMzkA*%Fvb4MITFa=+Eo3^t5Tw(qFV+cXM$%{ni7| zElg{yiIQ93gD=4RAIdbeugLn@K04RGyu2JK4(LbMdnJ3~@n0z^DJcSUI(-rYlUo0I zHOK_bRp8kvwg;8%h`@kx(q}>xGg4Bd+4p30baZGNo11=+&nxruUSZC=a)KSYs5iU8 zJawkBXubw}d_A@+$qfpHo)c-o&h?~q%`7fZD3k|dIguRyAOn!edr-#%?IYbrA#-6V z?$*}UfnDJEmmoDwO}4_6ncVdr7Ml&w)7Q__%$hjCN9-VMiMx)BM`10Qi?=Ct`9w*Q zqVU-uZf(w0OF6I6TKgw9F%df(3uF8H`z=?tWVe6($d8`u0fzq=n6JE;d*@G1ZaM#> za@z(d|6Mvc{@Dde!5v>|^lZUF1C~A%Dpe}hYgEBP`<{xbYN(u?T=2&ywttTVd_pK~ z&?_rd*o%uk1pW%zW1iNeWIooCy^LRn)S41bSWs{lH6TxtIl>vK{#g9VFO*2sA?W7C za*XaKXJoirz*i?416M|>uT5l=Ed&+XrrwzP$IPN}s*tBUvMWL1;Y*e|8Vi2xntoRX zIan{oQQY&ywtbOrN^0snacO{tfJ=hG5nyrgwWA8=RB!yG*~h#JUbEyEy*nkcgzo9$ z=no}GS*-#8&=TFtV!EM4yEXhFW%uukr>ExEhku_MD9NQ#4GiVwI}4Sv_6vMG(hVS@ z{igb>4tcZn!|y(1-(s8;t+?=(F|0vSoQa{XO zq6%m-o+^Ax)LjH@#Zf*->$5lSE0-lI*#&_eH!r?RwR%Eg(QQe*J*)`HYZq#4%zP zbc&nUE=LG#c*d03E*^+aDy6mR_KSnW#3~)D&_x`TCeJtN=6$OxZB?&wetKH20Q0F9 zV%dcP)sW*N`3O7+tDJDcr6p!>D(n{_#G!+1H~NF)c5Et(k+c0cLCnoj=8yXtm91iEJ!q0h-!Jdv83NL%AI!Fotxi?28#5ZuS>pR=Ai z4cb~+F{+ztkXbu|CA`&?mDX*_cn8fY;_scVz1M4NVVhBUCB`A!B&PkhZWq-r z*)yIP0Pw_p`8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs index 1f94b4c7..86cac7e3 100644 --- a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs @@ -28,10 +28,12 @@ public bool OldCharacterSoundsEnabled set => App.Settings.Prop.UseOldCharacterSounds = value; } - public bool OldMouseCursorEnabled + public IReadOnlyDictionary CursorTypes => CursorTypeEx.Selections; + + public string SelectedCursorType { - get => App.Settings.Prop.UseOldMouseCursor; - set => App.Settings.Prop.UseOldMouseCursor = value; + get => CursorTypes.FirstOrDefault(x => x.Value == App.Settings.Prop.CursorType).Key; + set => App.Settings.Prop.CursorType = CursorTypes[value]; } public bool DisableAppPatchEnabled From f3b7bbbbc6bf5674a73f1381c5b4df9e8b2950a6 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 00:07:36 +0100 Subject: [PATCH 087/178] turns out its 2008 and not 2009... --- Bloxstrap/Enums/BootstrapperIcon.cs | 2 +- Bloxstrap/Enums/BootstrapperStyle.cs | 2 +- Bloxstrap/Extensions/BootstrapperIconEx.cs | 2 +- Bloxstrap/Properties/Resources.Designer.cs | 4 ++-- Bloxstrap/UI/Controls.cs | 2 +- ...og2009.Designer.cs => LegacyDialog2008.Designer.cs} | 10 +++++----- .../{LegacyDialog2009.cs => LegacyDialog2008.cs} | 6 +++--- .../{LegacyDialog2009.resx => LegacyDialog2008.resx} | 0 Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs | 6 +++--- 9 files changed, 17 insertions(+), 17 deletions(-) rename Bloxstrap/UI/Elements/Bootstrapper/{LegacyDialog2009.Designer.cs => LegacyDialog2008.Designer.cs} (95%) rename Bloxstrap/UI/Elements/Bootstrapper/{LegacyDialog2009.cs => LegacyDialog2008.cs} (86%) rename Bloxstrap/UI/Elements/Bootstrapper/{LegacyDialog2009.resx => LegacyDialog2008.resx} (100%) diff --git a/Bloxstrap/Enums/BootstrapperIcon.cs b/Bloxstrap/Enums/BootstrapperIcon.cs index 4a44b878..a67185d9 100644 --- a/Bloxstrap/Enums/BootstrapperIcon.cs +++ b/Bloxstrap/Enums/BootstrapperIcon.cs @@ -3,7 +3,7 @@ public enum BootstrapperIcon { IconBloxstrap, - Icon2009, + Icon2008, Icon2011, IconEarly2015, IconLate2015, diff --git a/Bloxstrap/Enums/BootstrapperStyle.cs b/Bloxstrap/Enums/BootstrapperStyle.cs index cade7cbd..2d1b0633 100644 --- a/Bloxstrap/Enums/BootstrapperStyle.cs +++ b/Bloxstrap/Enums/BootstrapperStyle.cs @@ -3,7 +3,7 @@ public enum BootstrapperStyle { VistaDialog, - LegacyDialog2009, + LegacyDialog2008, LegacyDialog2011, ProgressDialog, FluentDialog, diff --git a/Bloxstrap/Extensions/BootstrapperIconEx.cs b/Bloxstrap/Extensions/BootstrapperIconEx.cs index 5b8721b4..dad9cefb 100644 --- a/Bloxstrap/Extensions/BootstrapperIconEx.cs +++ b/Bloxstrap/Extensions/BootstrapperIconEx.cs @@ -33,7 +33,7 @@ public static Icon GetIcon(this BootstrapperIcon icon) return icon switch { BootstrapperIcon.IconBloxstrap => Properties.Resources.IconBloxstrap, - BootstrapperIcon.Icon2009 => Properties.Resources.Icon2009, + BootstrapperIcon.Icon2008 => Properties.Resources.Icon2008, BootstrapperIcon.Icon2011 => Properties.Resources.Icon2011, BootstrapperIcon.IconEarly2015 => Properties.Resources.IconEarly2015, BootstrapperIcon.IconLate2015 => Properties.Resources.IconLate2015, diff --git a/Bloxstrap/Properties/Resources.Designer.cs b/Bloxstrap/Properties/Resources.Designer.cs index 2e365792..a65c8d7d 100644 --- a/Bloxstrap/Properties/Resources.Designer.cs +++ b/Bloxstrap/Properties/Resources.Designer.cs @@ -115,11 +115,11 @@ internal static System.Drawing.Icon IconBloxstrap /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// - internal static System.Drawing.Icon Icon2009 + internal static System.Drawing.Icon Icon2008 { get { - object obj = ResourceManager.GetObject("Icon2009", resourceCulture); + object obj = ResourceManager.GetObject("Icon2008", resourceCulture); return ((System.Drawing.Icon)(obj)); } } diff --git a/Bloxstrap/UI/Controls.cs b/Bloxstrap/UI/Controls.cs index 22a6a61c..34115be9 100644 --- a/Bloxstrap/UI/Controls.cs +++ b/Bloxstrap/UI/Controls.cs @@ -47,7 +47,7 @@ public static IBootstrapperDialog GetBootstrapperDialog(BootstrapperStyle style) return style switch { BootstrapperStyle.VistaDialog => new VistaDialog(), - BootstrapperStyle.LegacyDialog2009 => new LegacyDialog2009(), + BootstrapperStyle.LegacyDialog2008 => new LegacyDialog2008(), BootstrapperStyle.LegacyDialog2011 => new LegacyDialog2011(), BootstrapperStyle.ProgressDialog => new ProgressDialog(), BootstrapperStyle.FluentDialog => new FluentDialog(), diff --git a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.Designer.cs b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.Designer.cs similarity index 95% rename from Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.Designer.cs rename to Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.Designer.cs index d5186946..2da060af 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.Designer.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.Designer.cs @@ -2,7 +2,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper { - partial class LegacyDialog2009 + partial class LegacyDialog2008 { /// /// Required designer variable. @@ -65,7 +65,7 @@ private void InitializeComponent() this.buttonCancel.UseVisualStyleBackColor = true; this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click); // - // LegacyDialog2009 + // LegacyDialog2008 // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; @@ -79,10 +79,10 @@ private void InitializeComponent() this.MaximumSize = new System.Drawing.Size(327, 161); this.MinimizeBox = false; this.MinimumSize = new System.Drawing.Size(327, 161); - this.Name = "LegacyDialog2009"; + this.Name = "LegacyDialog2008"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "LegacyDialog2009"; - this.Load += new System.EventHandler(this.LegacyDialog2009_Load); + this.Text = "LegacyDialog2008"; + this.Load += new System.EventHandler(this.LegacyDialog2008_Load); this.ResumeLayout(false); } diff --git a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.cs b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs similarity index 86% rename from Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.cs rename to Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs index f66fdfaa..a84042cb 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs @@ -8,7 +8,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper // windows: https://youtu.be/VpduiruysuM?t=18 // mac: https://youtu.be/ncHhbcVDRgQ?t=63 - public partial class LegacyDialog2009 : WinFormsDialogBase + public partial class LegacyDialog2008 : WinFormsDialogBase { protected override string _message { @@ -34,7 +34,7 @@ protected override bool _cancelEnabled set => this.buttonCancel.Enabled = value; } - public LegacyDialog2009() + public LegacyDialog2008() { InitializeComponent(); @@ -42,7 +42,7 @@ public LegacyDialog2009() SetupDialog(); } - private void LegacyDialog2009_Load(object sender, EventArgs e) + private void LegacyDialog2008_Load(object sender, EventArgs e) { this.Activate(); } diff --git a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.resx b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.resx similarity index 100% rename from Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2009.resx rename to Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.resx diff --git a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs index 489c8fd9..4e5e6f10 100644 --- a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs @@ -77,8 +77,8 @@ public string Theme { "Fluent", BootstrapperStyle.FluentDialog }, { "Progress (~2014)", BootstrapperStyle.ProgressDialog }, { "Legacy (2011 - 2014)", BootstrapperStyle.LegacyDialog2011 }, - { "Legacy (2009 - 2011)", BootstrapperStyle.LegacyDialog2009 }, - { "Vista (2009 - 2011)", BootstrapperStyle.VistaDialog }, + { "Legacy (2008 - 2011)", BootstrapperStyle.LegacyDialog2008 }, + { "Vista (2008 - 2011)", BootstrapperStyle.VistaDialog }, { "Fake Byfron (2023)", BootstrapperStyle.ByfronDialog }, }; @@ -97,7 +97,7 @@ public string Dialog { "Late 2015", BootstrapperIcon.IconLate2015 }, { "Early 2015", BootstrapperIcon.IconEarly2015 }, { "2011", BootstrapperIcon.Icon2011 }, - { "2009", BootstrapperIcon.Icon2009 }, + { "2008", BootstrapperIcon.Icon2008 }, { "Custom", BootstrapperIcon.IconCustom }, }; From 258746f5fa3ac67ba87b0709620d4984f70839c6 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 08:36:00 +0100 Subject: [PATCH 088/178] oops forgot this one --- Bloxstrap/Properties/Resources.resx | 4 ++-- Bloxstrap/Resources/{Icon2009.ico => Icon2008.ico} | Bin 2 files changed, 2 insertions(+), 2 deletions(-) rename Bloxstrap/Resources/{Icon2009.ico => Icon2008.ico} (100%) diff --git a/Bloxstrap/Properties/Resources.resx b/Bloxstrap/Properties/Resources.resx index af22cd59..7c24a626 100644 --- a/Bloxstrap/Properties/Resources.resx +++ b/Bloxstrap/Properties/Resources.resx @@ -130,8 +130,8 @@ ..\Resources\DarkCancelButtonHover.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\Icon2009.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\Icon2008.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\Icon2011.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/Bloxstrap/Resources/Icon2009.ico b/Bloxstrap/Resources/Icon2008.ico similarity index 100% rename from Bloxstrap/Resources/Icon2009.ico rename to Bloxstrap/Resources/Icon2008.ico From d8842cc0ccaf16b30a1a6edc507d9a2c672300b0 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 10:53:17 +0100 Subject: [PATCH 089/178] Add debug flags, fix mod preset bug --- Bloxstrap/Bootstrapper.cs | 18 ++++--- Bloxstrap/Extensions/CursorTypeEx.cs | 4 +- Bloxstrap/Models/Settings.cs | 1 + .../UI/Elements/Menu/Pages/FastFlagsPage.xaml | 31 ++++++++++++ .../UI/ViewModels/Menu/FastFlagsViewModel.cs | 47 +++++++++++++++++-- 5 files changed, 88 insertions(+), 13 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 16059f88..98e21396 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1110,22 +1110,26 @@ private async Task ApplyModifications() private static async Task CheckModPreset(bool condition, string location, string name) { string fullLocation = Path.Combine(Directories.Modifications, location); - byte[] embeddedData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); - string fileHash = File.Exists(fullLocation) ? Utility.MD5Hash.FromFile(fullLocation) : ""; + + if (!condition) + { + if (fileHash != "") + File.Delete(fullLocation); + + return; + } + + byte[] embeddedData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); string embeddedHash = Utility.MD5Hash.FromBytes(embeddedData); - if (condition && fileHash != embeddedHash) + if (fileHash != embeddedHash) { Directory.CreateDirectory(Path.GetDirectoryName(fullLocation)!); File.Delete(fullLocation); await File.WriteAllBytesAsync(fullLocation, embeddedData); } - else if (!condition && fileHash != "") - { - File.Delete(fullLocation); - } } private async Task DownloadPackage(Package package) diff --git a/Bloxstrap/Extensions/CursorTypeEx.cs b/Bloxstrap/Extensions/CursorTypeEx.cs index 3afe6926..d2ba437b 100644 --- a/Bloxstrap/Extensions/CursorTypeEx.cs +++ b/Bloxstrap/Extensions/CursorTypeEx.cs @@ -9,8 +9,8 @@ static class CursorTypeEx public static IReadOnlyDictionary Selections => new Dictionary { { "Default", CursorType.Default }, - { "Before 2022", CursorType.From2013 }, - { "Before 2013", CursorType.From2006 }, + { "2013 - 2022", CursorType.From2013 }, + { "2006 - 2013", CursorType.From2006 }, }; } } diff --git a/Bloxstrap/Models/Settings.cs b/Bloxstrap/Models/Settings.cs index 604e3c20..104509f3 100644 --- a/Bloxstrap/Models/Settings.cs +++ b/Bloxstrap/Models/Settings.cs @@ -15,6 +15,7 @@ public class Settings public bool CheckForUpdates { get; set; } = true; public bool CreateDesktopIcon { get; set; } = true; public bool MultiInstanceLaunching { get; set; } = false; + public bool OhHeyYouFoundMe { get; set; } = false; // channel configuration public string Channel { get; set; } = RobloxDeployment.DefaultChannel; diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml index 5fa2d850..5a49eaf1 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml @@ -41,6 +41,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs index 566324ce..f1a17061 100644 --- a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs @@ -1,6 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.IO; +using System.Linq; +using System.Windows; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; @@ -16,6 +19,42 @@ public class FastFlagsViewModel : INotifyPropertyChanged private void OpenClientSettings() => Utilities.ShellExecute(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); + public Visibility ShowDebugFlags => App.Settings.Prop.OhHeyYouFoundMe ? Visibility.Visible : Visibility.Collapsed; + + public bool HttpRequestLogging + { + get => App.FastFlags.GetValue("DFLogHttpTraceLight") is not null; + set => App.FastFlags.SetValue("DFLogHttpTraceLight", value ? 12 : null); + } + + public string HttpRequestProxy + { + get => App.FastFlags.GetValue("DFStringDebugPlayerHttpProxyUrl") ?? ""; + + set + { + bool? boolValue = null; + string? stringValue = null; + + if (!String.IsNullOrEmpty(value)) + { + boolValue = true; + stringValue = value; + } + + App.FastFlags.SetValue("DFFlagDebugEnableHttpProxy", boolValue); + App.FastFlags.SetValue("DFStringDebugPlayerHttpProxyUrl", stringValue); + App.FastFlags.SetValue("DFStringHttpCurlProxyHostAndPort", stringValue); + App.FastFlags.SetValue("DFStringHttpCurlProxyHostAndPortForExternalUrl", stringValue); + } + } + + public string StateOverlayFlags + { + get => App.FastFlags.GetValue("FStringDebugShowFlagState") ?? ""; + set => App.FastFlags.SetValue("FStringDebugShowFlagState", String.IsNullOrEmpty(value) ? null : value); + } + public int FramerateLimit { get => int.TryParse(App.FastFlags.GetValue("DFIntTaskSchedulerTargetFps"), out int x) ? x : 60; @@ -111,18 +150,18 @@ public string SelectedLightingTechnology return mode.Key; } - return "Automatic"; + return LightingTechnologies.First().Key; } set { foreach (var mode in LightingTechnologies) { - if (mode.Key != "Automatic") + if (mode.Key != LightingTechnologies.First().Key) App.FastFlags.SetValue(mode.Value, null); } - if (value != "Automatic") + if (value != LightingTechnologies.First().Key) App.FastFlags.SetValue(LightingTechnologies[value], "True"); } } From 41ca47ad0b3f587bbceda5ae56f34429c7b2a013 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 11:01:14 +0100 Subject: [PATCH 090/178] Add button to reset chosen install location --- Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml | 4 +++- Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml index b478e7b5..72764105 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml @@ -23,9 +23,11 @@ + - + + diff --git a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs index 5a659f73..6ad864b0 100644 --- a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs @@ -11,7 +11,10 @@ public class InstallationViewModel : INotifyPropertyChanged public event PropertyChangedEventHandler? PropertyChanged; public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + private string _originalInstallLocation = App.BaseDirectory; + public ICommand BrowseInstallLocationCommand => new RelayCommand(BrowseInstallLocation); + public ICommand ResetInstallLocationCommand => new RelayCommand(ResetInstallLocation); public ICommand OpenFolderCommand => new RelayCommand(OpenFolder); private void BrowseInstallLocation() @@ -22,7 +25,12 @@ private void BrowseInstallLocation() return; InstallLocation = dialog.SelectedPath; + OnPropertyChanged(nameof(InstallLocation)); + } + private void ResetInstallLocation() + { + InstallLocation = _originalInstallLocation; OnPropertyChanged(nameof(InstallLocation)); } From 63ef9072468342a3c774ba6da834a480c243b880 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 12:47:27 +0100 Subject: [PATCH 091/178] Add bulk font replacement, Win32 for file picker --- Bloxstrap/Bootstrapper.cs | 41 ++++++++++++++++- Bloxstrap/Models/FontFace.cs | 20 ++++++++ Bloxstrap/Models/FontFamily.cs | 14 ++++++ .../Elements/Menu/Pages/InstallationPage.xaml | 2 +- .../UI/Elements/Menu/Pages/ModsPage.xaml | 16 ++++++- .../UI/ViewModels/Menu/AppearanceViewModel.cs | 18 ++++---- Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs | 46 +++++++++++++++++-- 7 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 Bloxstrap/Models/FontFace.cs create mode 100644 Bloxstrap/Models/FontFamily.cs diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 98e21396..cc64143e 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -5,6 +5,7 @@ using System.IO.Compression; using System.Linq; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -115,7 +116,7 @@ private void UpdateProgressBar() if (Dialog is not null) Dialog.ProgressValue = newProgress; } - + public async Task Run() { App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); @@ -1035,6 +1036,44 @@ private async Task ApplyModifications() await response.Content.CopyToAsync(fileStream); } + // check custom font mod + // instead of replacing the fonts themselves, we'll just alter the font family manifests + + string modFontFamiliesFolder = Path.Combine(Directories.Modifications, "content\\fonts\\families"); + string customFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\CustomFont.ttf"); + + if (File.Exists(customFontLocation)) + { + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] Begin font check"); + + Directory.CreateDirectory(modFontFamiliesFolder); + + foreach (string jsonFilePath in Directory.GetFiles(Path.Combine(_versionFolder, "content\\fonts\\families"))) + { + string jsonFilename = Path.GetFileName(jsonFilePath); + string modFilepath = Path.Combine(modFontFamiliesFolder, jsonFilename); + + if (File.Exists(modFilepath)) + continue; + + FontFamily? fontFamilyData = JsonSerializer.Deserialize(File.ReadAllText(jsonFilePath)); + + if (fontFamilyData is null) + continue; + + foreach (FontFace fontFace in fontFamilyData.Faces) + fontFace.AssetId = "rbxasset://fonts/CustomFont.ttf"; + + File.WriteAllText(modFilepath, JsonSerializer.Serialize(fontFamilyData, new JsonSerializerOptions { WriteIndented = true })); + } + + App.Logger.WriteLine("[Bootstrapper::ApplyModifications] End font check"); + } + else + { + Directory.Delete(modFontFamiliesFolder, true); + } + foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories)) { // get relative directory path diff --git a/Bloxstrap/Models/FontFace.cs b/Bloxstrap/Models/FontFace.cs new file mode 100644 index 00000000..50bb179c --- /dev/null +++ b/Bloxstrap/Models/FontFace.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Bloxstrap.Models +{ + public class FontFace + { + [JsonPropertyName("name")] + public string Name { get; set; } = null!; + + [JsonPropertyName("weight")] + public int Weight { get; set; } + + [JsonPropertyName("style")] + public string Style { get; set; } = null!; + + [JsonPropertyName("assetId")] + public string AssetId { get; set; } = null!; + } +} diff --git a/Bloxstrap/Models/FontFamily.cs b/Bloxstrap/Models/FontFamily.cs new file mode 100644 index 00000000..9a846e1e --- /dev/null +++ b/Bloxstrap/Models/FontFamily.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Bloxstrap.Models +{ + public class FontFamily + { + [JsonPropertyName("name")] + public string Name { get; set; } = null!; + + [JsonPropertyName("faces")] + public IEnumerable Faces { get; set; } = null!; + } +} diff --git a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml index 72764105..2790bc2a 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml @@ -27,7 +27,7 @@ - + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml index 9e3e57e9..c69873dd 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml @@ -113,6 +113,20 @@ + + + + + + Forces every in-game font to be a font that you choose. + + + + + + + + @@ -122,7 +136,7 @@ - + diff --git a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs index 4e5e6f10..c22ba1f1 100644 --- a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Windows; using System.Windows.Controls; -using System.Windows.Forms; +using Microsoft.Win32; using System.Windows.Input; using System.Windows.Media; @@ -40,14 +40,16 @@ private void PreviewBootstrapper() private void BrowseCustomIconLocation() { - using var dialog = new OpenFileDialog(); - dialog.Filter = "Icon files (*.ico)|*.ico|All files (*.*)|*.*"; - - if (dialog.ShowDialog() == DialogResult.OK) + var dialog = new OpenFileDialog { - CustomIconLocation = dialog.FileName; - OnPropertyChanged(nameof(CustomIconLocation)); - } + Filter = "Icon files|*.ico|All files|*.*" + }; + + if (dialog.ShowDialog() != true) + return; + + CustomIconLocation = dialog.FileName; + OnPropertyChanged(nameof(CustomIconLocation)); } public AppearanceViewModel(Page page) diff --git a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs index 86cac7e3..b02209fe 100644 --- a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs @@ -1,21 +1,56 @@ using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Windows; using System.Windows.Input; using Bloxstrap.Enums; using Bloxstrap.Extensions; +using Microsoft.Win32; + using CommunityToolkit.Mvvm.Input; namespace Bloxstrap.UI.ViewModels.Menu { - public class ModsViewModel + public class ModsViewModel : INotifyPropertyChanged { - public ICommand OpenModsFolderCommand => new RelayCommand(OpenModsFolder); + public event PropertyChangedEventHandler? PropertyChanged; + public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); private void OpenModsFolder() => Process.Start("explorer.exe", Directories.Modifications); + private string _customFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\CustomFont.ttf"); + private bool _usingCustomFont => File.Exists(_customFontLocation); + + private void ManageCustomFont() + { + if (_usingCustomFont) + { + File.Delete(_customFontLocation); + } + else + { + var dialog = new OpenFileDialog + { + Filter = "Font files|*.ttf;*.otf|All files|*.*" + }; + + if (dialog.ShowDialog() != true) + return; + + Directory.CreateDirectory(Path.GetDirectoryName(_customFontLocation)!); + File.Copy(dialog.FileName, _customFontLocation); + } + + OnPropertyChanged(nameof(ChooseCustomFontVisibility)); + OnPropertyChanged(nameof(DeleteCustomFontVisibility)); + } + + public ICommand OpenModsFolderCommand => new RelayCommand(OpenModsFolder); + public bool OldDeathSoundEnabled { get => App.Settings.Prop.UseOldDeathSound; @@ -50,7 +85,12 @@ public string SelectedEmojiType set => App.Settings.Prop.EmojiType = EmojiTypes[value]; } - public bool DisableFullscreenOptimizationsEnabled + public Visibility ChooseCustomFontVisibility => _usingCustomFont ? Visibility.Collapsed : Visibility.Visible; + public Visibility DeleteCustomFontVisibility => _usingCustomFont ? Visibility.Visible : Visibility.Collapsed; + + public ICommand ManageCustomFontCommand => new RelayCommand(ManageCustomFont); + + public bool DisableFullscreenOptimizations { get => App.Settings.Prop.DisableFullscreenOptimizations; set => App.Settings.Prop.DisableFullscreenOptimizations = value; From 78869e5e7e21f1633ac905de239807caeecbd5e5 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 12:59:18 +0100 Subject: [PATCH 092/178] Default to LIVE if no launch channel set also fixed a bug with the font mod --- Bloxstrap/Bootstrapper.cs | 2 +- Bloxstrap/ProtocolHandler.cs | 51 ++++++++++++------- .../UI/Elements/Menu/Pages/BehaviourPage.xaml | 4 +- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index cc64143e..8f6c9756 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1069,7 +1069,7 @@ private async Task ApplyModifications() App.Logger.WriteLine("[Bootstrapper::ApplyModifications] End font check"); } - else + else if (Directory.Exists(modFontFamiliesFolder)) { Directory.Delete(modFontFamiliesFolder, true); } diff --git a/Bloxstrap/ProtocolHandler.cs b/Bloxstrap/ProtocolHandler.cs index ce1a4ace..4d4c58c1 100644 --- a/Bloxstrap/ProtocolHandler.cs +++ b/Bloxstrap/ProtocolHandler.cs @@ -32,6 +32,8 @@ public static string ParseUri(string protocol) string[] keyvalPair; string key; string val; + bool channelArgPresent = false; + StringBuilder commandLine = new(); foreach (var parameter in protocol.Split('+')) @@ -56,25 +58,10 @@ public static string ParseUri(string protocol) if (key == "launchtime") val = "LAUNCHTIMEPLACEHOLDER"; - if (key == "channel") + if (key == "channel" && !String.IsNullOrEmpty(val)) { - if (val.ToLowerInvariant() != App.Settings.Prop.Channel.ToLowerInvariant() && App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Ignore) - { - MessageBoxResult result = App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Automatic - ? MessageBoxResult.Yes - : Controls.ShowMessageBox( - $"Roblox is attempting to set your channel to {val}, however your current preferred channel is {App.Settings.Prop.Channel}.\n\n" + - $"Would you like to switch channels from {App.Settings.Prop.Channel} to {val}?", - MessageBoxImage.Question, - MessageBoxButton.YesNo - ); - - if (result == MessageBoxResult.Yes) - { - App.Logger.WriteLine($"[Protocol::ParseUri] Changed Roblox build channel from {App.Settings.Prop.Channel} to {val}"); - App.Settings.Prop.Channel = val; - } - } + channelArgPresent = true; + ChangeChannel(val); // we'll set the arg when launching continue; @@ -83,9 +70,37 @@ public static string ParseUri(string protocol) commandLine.Append(UriKeyArgMap[key] + val + " "); } + if (!channelArgPresent) + ChangeChannel(RobloxDeployment.DefaultChannel); + return commandLine.ToString(); } + public static void ChangeChannel(string channel) + { + if (channel.ToLowerInvariant() == App.Settings.Prop.Channel.ToLowerInvariant()) + return; + + if (App.Settings.Prop.ChannelChangeMode == ChannelChangeMode.Ignore) + return; + + if (App.Settings.Prop.ChannelChangeMode != ChannelChangeMode.Automatic) + { + MessageBoxResult result = Controls.ShowMessageBox( + $"Roblox is attempting to set your channel to {channel}, however your current preferred channel is {App.Settings.Prop.Channel}.\n\n" + + $"Would you like to switch channels from {App.Settings.Prop.Channel} to {channel}?", + MessageBoxImage.Question, + MessageBoxButton.YesNo + ); + + if (result != MessageBoxResult.Yes) + return; + } + + App.Logger.WriteLine($"[Protocol::ParseUri] Changed Roblox build channel from {App.Settings.Prop.Channel} to {channel}"); + App.Settings.Prop.Channel = channel; + } + public static void Register(string key, string name, string handler) { string handlerArgs = $"\"{handler}\" %1"; diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml index 9f28d66b..9d118b28 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml @@ -39,8 +39,8 @@ - - + + From 232cd4f5c0bf26acd7d0221550a3e2ce07bd1d43 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 13:12:46 +0100 Subject: [PATCH 093/178] Fix bug with mod preset checking... again --- Bloxstrap/Bootstrapper.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 8f6c9756..59e77142 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1000,9 +1000,11 @@ private async Task ApplyModifications() Directory.CreateDirectory(modFolder); // cursors - await CheckModPreset(App.Settings.Prop.CursorType != CursorType.Default, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", $"Cursor.{App.Settings.Prop.CursorType}.ArrowCursor.png"); - await CheckModPreset(App.Settings.Prop.CursorType != CursorType.Default, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", $"Cursor.{App.Settings.Prop.CursorType}.ArrowFarCursor.png"); - + await CheckModPreset(App.Settings.Prop.CursorType == CursorType.From2006, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "Cursor.From2006.ArrowCursor.png"); + await CheckModPreset(App.Settings.Prop.CursorType == CursorType.From2006, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "Cursor.From2006.ArrowFarCursor.png"); + await CheckModPreset(App.Settings.Prop.CursorType == CursorType.From2013, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "Cursor.From2013.ArrowCursor.png"); + await CheckModPreset(App.Settings.Prop.CursorType == CursorType.From2013, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "Cursor.From2013.ArrowFarCursor.png"); + // character sounds await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_footsteps_plastic.mp3", "OldWalk.mp3"); await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\action_jump.mp3", "OldJump.mp3"); @@ -1151,17 +1153,17 @@ private static async Task CheckModPreset(bool condition, string location, string string fullLocation = Path.Combine(Directories.Modifications, location); string fileHash = File.Exists(fullLocation) ? Utility.MD5Hash.FromFile(fullLocation) : ""; + byte[] embeddedData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); + string embeddedHash = Utility.MD5Hash.FromBytes(embeddedData); + if (!condition) { - if (fileHash != "") + if (fileHash != "" && fileHash == embeddedHash) File.Delete(fullLocation); return; } - byte[] embeddedData = string.IsNullOrEmpty(name) ? Array.Empty() : await Resource.Get(name); - string embeddedHash = Utility.MD5Hash.FromBytes(embeddedData); - if (fileHash != embeddedHash) { Directory.CreateDirectory(Path.GetDirectoryName(fullLocation)!); From e3cf2ac3a2f07ac5d85e865d0f70f829bbfce798 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 13:18:39 +0100 Subject: [PATCH 094/178] Minor visual adjustments --- Bloxstrap/Extensions/CursorTypeEx.cs | 4 ++-- Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/Extensions/CursorTypeEx.cs b/Bloxstrap/Extensions/CursorTypeEx.cs index d2ba437b..a46dc7ec 100644 --- a/Bloxstrap/Extensions/CursorTypeEx.cs +++ b/Bloxstrap/Extensions/CursorTypeEx.cs @@ -9,8 +9,8 @@ static class CursorTypeEx public static IReadOnlyDictionary Selections => new Dictionary { { "Default", CursorType.Default }, - { "2013 - 2022", CursorType.From2013 }, - { "2006 - 2013", CursorType.From2006 }, + { "2013 (Angular)", CursorType.From2013 }, + { "2006 (Cartoony)", CursorType.From2006 }, }; } } diff --git a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml index c69873dd..8972f0ff 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml @@ -123,7 +123,7 @@ - + From e4dc6c0600a1c7f5c393401c758576d10cbd0e71 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 16:20:28 +0100 Subject: [PATCH 095/178] Show inner exception in error dialog --- Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs b/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs index 1af61aa7..2b71bcb7 100644 --- a/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs +++ b/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs @@ -18,11 +18,16 @@ public partial class ExceptionDialog { public ExceptionDialog(Exception exception) { + Exception? innerException = exception.InnerException; + InitializeComponent(); Title = RootTitleBar.Title = $"{App.ProjectName} Exception"; ErrorRichTextBox.Selection.Text = $"{exception.GetType()}: {exception.Message}"; + if (innerException is not null) + ErrorRichTextBox.Selection.Text += $"\n\n===== Inner Exception =====\n{innerException.GetType()}: {innerException.Message}"; + if (!App.Logger.Initialized) LocateLogFileButton.Content = "Copy log contents"; From f553a812cbc84dcf8f03f04b8355becea5f6f357 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 17:33:12 +0100 Subject: [PATCH 096/178] Add ability to set old avatar editor scene (#353) --- Bloxstrap/Bloxstrap.csproj | 1 + Bloxstrap/Bootstrapper.cs | 7 ++++-- Bloxstrap/Models/Settings.cs | 1 + .../Resources/Mods/OldAvatarBackground.rbxl | Bin 0 -> 161011 bytes .../UI/Elements/Menu/Pages/ModsPage.xaml | 22 +++++++++++++----- Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs | 6 +++++ 6 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 Bloxstrap/Resources/Mods/OldAvatarBackground.rbxl diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index f1ce5f15..5bd23b2e 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -29,6 +29,7 @@ + diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 59e77142..f9f263f5 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -999,6 +999,8 @@ private async Task ApplyModifications() if (!Directory.Exists(modFolder)) Directory.CreateDirectory(modFolder); + bool appDisabled = App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"); + // cursors await CheckModPreset(App.Settings.Prop.CursorType == CursorType.From2006, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", "Cursor.From2006.ArrowCursor.png"); await CheckModPreset(App.Settings.Prop.CursorType == CursorType.From2006, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", "Cursor.From2006.ArrowFarCursor.png"); @@ -1014,8 +1016,9 @@ private async Task ApplyModifications() await CheckModPreset(App.Settings.Prop.UseOldCharacterSounds, @"content\sounds\impact_water.mp3", "Empty.mp3"); await CheckModPreset(App.Settings.Prop.UseOldDeathSound, @"content\sounds\ouch.ogg", "OldDeath.ogg"); - // misc - await CheckModPreset(App.Settings.Prop.UseDisableAppPatch && !_launchCommandLine.Contains("--deeplink"), @"ExtraContent\places\Mobile.rbxl", ""); + // Mobile.rbxl + await CheckModPreset(appDisabled, @"ExtraContent\places\Mobile.rbxl", ""); + await CheckModPreset(App.Settings.Prop.UseOldAvatarBackground && !appDisabled, @"ExtraContent\places\Mobile.rbxl", "OldAvatarBackground.rbxl"); // emoji presets are downloaded remotely from github due to how large they are string contentFonts = Path.Combine(Directories.Modifications, "content\\fonts"); diff --git a/Bloxstrap/Models/Settings.cs b/Bloxstrap/Models/Settings.cs index 104509f3..95fd18f4 100644 --- a/Bloxstrap/Models/Settings.cs +++ b/Bloxstrap/Models/Settings.cs @@ -31,6 +31,7 @@ public class Settings public bool UseOldDeathSound { get; set; } = true; public bool UseOldCharacterSounds { get; set; } = false; public bool UseDisableAppPatch { get; set; } = false; + public bool UseOldAvatarBackground { get; set; } = false; public CursorType CursorType { get; set; } = CursorType.Default; public EmojiType EmojiType { get; set; } = EmojiType.Default; public bool DisableFullscreenOptimizations { get; set; } = false; diff --git a/Bloxstrap/Resources/Mods/OldAvatarBackground.rbxl b/Bloxstrap/Resources/Mods/OldAvatarBackground.rbxl new file mode 100644 index 0000000000000000000000000000000000000000..578e822d42457e69a7621f106c2930bd1b047333 GIT binary patch literal 161011 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 - + @@ -71,17 +71,27 @@ - + - + - + + + + + + + + + + + @@ -91,7 +101,7 @@ - + @@ -101,7 +111,7 @@ - + diff --git a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs index b02209fe..7859f4af 100644 --- a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs @@ -71,6 +71,12 @@ public string SelectedCursorType set => App.Settings.Prop.CursorType = CursorTypes[value]; } + public bool OldAvatarBackground + { + get => App.Settings.Prop.UseOldAvatarBackground; + set => App.Settings.Prop.UseOldAvatarBackground = value; + } + public bool DisableAppPatchEnabled { get => App.Settings.Prop.UseDisableAppPatch; From 0162dbf3bb88a5fd43ae4439bb2ba51ccb34c940 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 17:52:59 +0100 Subject: [PATCH 097/178] Make channel selection input more responsive --- .../UI/Elements/Menu/Pages/BehaviourPage.xaml | 2 +- .../UI/Elements/Menu/Pages/BehaviourPage.xaml.cs | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml index 9d118b28..50c85ca7 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml @@ -42,7 +42,7 @@ - + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs index db864e10..736197b7 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs @@ -17,21 +17,5 @@ public BehaviourPage() DataContext = new BehaviourViewModel(); InitializeComponent(); } - - // https://stackoverflow.com/a/13289118/11852173 - // yes this doesnt fully conform to xaml but whatever - private void ComboBox_KeyEnterUpdate(object sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - { - ComboBox box = (ComboBox)sender; - DependencyProperty prop = ComboBox.TextProperty; - - BindingExpression binding = BindingOperations.GetBindingExpression(box, prop); - - if (binding is not null) - binding.UpdateSource(); - } - } } } From 1002199db467186ef4667706624f254c6eb759cf Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 20:49:58 +0100 Subject: [PATCH 098/178] Make uninstall process clearer --- .../Elements/Menu/Pages/InstallationPage.xaml | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml index 2790bc2a..24997736 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml @@ -12,7 +12,7 @@ - + @@ -31,22 +31,36 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + From 9f9156b4cf30bd040879500ab5e0729fba2cdb4a Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 22:01:57 +0100 Subject: [PATCH 099/178] Make installation information clearer --- Bloxstrap/Bloxstrap.csproj | 1 + .../Resources/Menu/StartMenuLocation.png | Bin 0 -> 200155 bytes Bloxstrap/UI/Elements/Menu/MainWindow.xaml | 6 +- .../Elements/Menu/Pages/PreInstallPage.xaml | 29 +++++++++ .../Menu/Pages/PreInstallPage.xaml.cs | 13 ++++ .../UI/ViewModels/Menu/MainWindowViewModel.cs | 57 +++++++++++------- 6 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 Bloxstrap/Resources/Menu/StartMenuLocation.png create mode 100644 Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml create mode 100644 Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml.cs diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 5bd23b2e..b5e501f7 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -17,6 +17,7 @@ + diff --git a/Bloxstrap/Resources/Menu/StartMenuLocation.png b/Bloxstrap/Resources/Menu/StartMenuLocation.png new file mode 100644 index 0000000000000000000000000000000000000000..208e68d0a60a543556cf65ca645fa87bd3439f37 GIT binary patch literal 200155 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%0Dh|e>Ucg9 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

D%M#z}#$`yz|O~bwA{)ZnaPo4Wt`Np?j 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 - + @@ -42,6 +42,8 @@ + + @@ -68,7 +70,7 @@ - + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml new file mode 100644 index 00000000..6b174dad --- /dev/null +++ b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml.cs new file mode 100644 index 00000000..04793ef7 --- /dev/null +++ b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml.cs @@ -0,0 +1,13 @@ +namespace Bloxstrap.UI.Menu.Pages +{ + ///

+ /// Interaction logic for PreInstallPage.xaml + /// + public partial class PreInstallPage + { + public PreInstallPage() + { + InitializeComponent(); + } + } +} diff --git a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs index 2a239a43..91c88f54 100644 --- a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs @@ -1,5 +1,8 @@ using System; +using System.ComponentModel; using System.IO; +using System.Linq; +using System.Threading.Tasks; using System.Windows; using System.Windows.Input; @@ -7,15 +10,17 @@ using CommunityToolkit.Mvvm.Input; -using Wpf.Ui.Controls.Interfaces; using Wpf.Ui.Mvvm.Contracts; -using System.Linq; +using Bloxstrap.UI.Menu.Pages; namespace Bloxstrap.UI.ViewModels.Menu { - public class MainWindowViewModel + public class MainWindowViewModel : INotifyPropertyChanged { + public event PropertyChangedEventHandler? PropertyChanged; + public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + private readonly Window _window; private readonly IDialogService _dialogService; private readonly string _originalBaseDirectory = App.BaseDirectory; // we need this to check if the basedirectory changes @@ -23,7 +28,9 @@ public class MainWindowViewModel public ICommand CloseWindowCommand => new RelayCommand(CloseWindow); public ICommand ConfirmSettingsCommand => new RelayCommand(ConfirmSettings); + public Visibility NavigationVisibility { get; set; } = Visibility.Visible; public string ConfirmButtonText => App.IsFirstRun ? "Install" : "Save"; + public bool ConfirmButtonEnabled { get; set; } = true; public MainWindowViewModel(Window window, IDialogService dialogService) { @@ -90,7 +97,32 @@ private void ConfirmSettings() } } - if (!App.IsFirstRun) + if (App.IsFirstRun) + { + if (NavigationVisibility == Visibility.Visible) + { + ((INavigationWindow)_window).Navigate(typeof(PreInstallPage)); + + NavigationVisibility = Visibility.Collapsed; + ConfirmButtonEnabled = false; + + OnPropertyChanged(nameof(NavigationVisibility)); + OnPropertyChanged(nameof(ConfirmButtonEnabled)); + + Task.Run(async delegate + { + await Task.Delay(3000); + ConfirmButtonEnabled = true; + OnPropertyChanged(nameof(ConfirmButtonEnabled)); + }); + } + else + { + App.IsSetupComplete = true; + CloseWindow(); + } + } + else { App.ShouldSaveConfigs = true; App.FastFlags.Save(); @@ -112,23 +144,6 @@ private void ConfirmSettings() CloseWindow(); } - else - { - IDialogControl dialogControl = _dialogService.GetDialogControl(); - - dialogControl.ButtonRightClick += (_, _) => - { - dialogControl.Hide(); - App.IsSetupComplete = true; - CloseWindow(); - }; - - dialogControl.ShowAndWaitAsync( - "What to know before you install", - "After installation, you can open this menu again by searching for it in the Start menu.\n" + - "If you want to revert back to the original Roblox launcher, just uninstall Bloxstrap and it will automatically revert." - ); - } } } } From eeeb33fed2f99810bb987cbb9e3bb2cc3f8068c0 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 22:03:27 +0100 Subject: [PATCH 100/178] Update wpfui (ebe4974 -> 5f322e73b) --- wpfui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpfui b/wpfui index ebe4974d..5f322e73 160000 --- a/wpfui +++ b/wpfui @@ -1 +1 @@ -Subproject commit ebe4974d29c5af8b9a236767054c8070b976a125 +Subproject commit 5f322e73b22d2bf3d0c052e845530b4e418d4be0 From 77725ea5d7d5d2bdcca8449cb2371a5b2e80ac72 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 22:30:52 +0100 Subject: [PATCH 101/178] Consolidate NotifyPropertyChanged ViewModels --- .../Bootstrapper/BootstrapperDialogViewModel.cs | 5 +---- .../Bootstrapper/ByfronDialogViewModel.cs | 2 +- .../UI/ViewModels/Menu/AppearanceViewModel.cs | 5 +---- .../UI/ViewModels/Menu/BehaviourViewModel.cs | 5 +---- .../UI/ViewModels/Menu/FastFlagsViewModel.cs | 5 +---- .../UI/ViewModels/Menu/InstallationViewModel.cs | 5 +---- .../UI/ViewModels/Menu/IntegrationsViewModel.cs | 5 +---- .../UI/ViewModels/Menu/MainWindowViewModel.cs | 5 +---- Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs | 5 +---- .../ViewModels/NotifyPropertyChangedViewModel.cs | 15 +++++++++++++++ 10 files changed, 24 insertions(+), 33 deletions(-) create mode 100644 Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs diff --git a/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs b/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs index 95866b66..5867d5c4 100644 --- a/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs @@ -9,11 +9,8 @@ namespace Bloxstrap.UI.ViewModels.Bootstrapper { - public class BootstrapperDialogViewModel : INotifyPropertyChanged + public class BootstrapperDialogViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private readonly IBootstrapperDialog _dialog; public ICommand CancelInstallCommand => new RelayCommand(CancelInstall); diff --git a/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs b/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs index 4cc3d686..568fe34b 100644 --- a/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs @@ -8,7 +8,7 @@ namespace Bloxstrap.UI.ViewModels.Bootstrapper { - public class ByfronDialogViewModel : BootstrapperDialogViewModel, INotifyPropertyChanged + public class ByfronDialogViewModel : BootstrapperDialogViewModel { // Using dark theme for default values. public ImageSource ByfronLogoLocation { get; set; } = new BitmapImage(new Uri("pack://application:,,,/Resources/BootstrapperStyles/ByfronDialog/ByfronLogoDark.jpg")); diff --git a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs index c22ba1f1..19a5224b 100644 --- a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs @@ -15,11 +15,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class AppearanceViewModel : INotifyPropertyChanged + public class AppearanceViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private readonly Page _page; public ICommand PreviewBootstrapperCommand => new RelayCommand(PreviewBootstrapper); diff --git a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs index 331c9974..07688194 100644 --- a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs @@ -12,11 +12,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class BehaviourViewModel : INotifyPropertyChanged + public class BehaviourViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private bool _manualChannelEntry = !RobloxDeployment.SelectableChannels.Contains(App.Settings.Prop.Channel); public BehaviourViewModel() diff --git a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs index f1a17061..30ea3703 100644 --- a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs @@ -10,11 +10,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class FastFlagsViewModel : INotifyPropertyChanged + public class FastFlagsViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - public ICommand OpenClientSettingsCommand => new RelayCommand(OpenClientSettings); private void OpenClientSettings() => Utilities.ShellExecute(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); diff --git a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs index 6ad864b0..389abe84 100644 --- a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs @@ -6,11 +6,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class InstallationViewModel : INotifyPropertyChanged + public class InstallationViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private string _originalInstallLocation = App.BaseDirectory; public ICommand BrowseInstallLocationCommand => new RelayCommand(BrowseInstallLocation); diff --git a/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs index 5847e6e9..d0425ac6 100644 --- a/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs @@ -8,11 +8,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class IntegrationsViewModel : INotifyPropertyChanged + public class IntegrationsViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - public ICommand AddIntegrationCommand => new RelayCommand(AddIntegration); public ICommand DeleteIntegrationCommand => new RelayCommand(DeleteIntegration); diff --git a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs index 91c88f54..cad2e8d9 100644 --- a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs @@ -16,11 +16,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class MainWindowViewModel : INotifyPropertyChanged + public class MainWindowViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private readonly Window _window; private readonly IDialogService _dialogService; private readonly string _originalBaseDirectory = App.BaseDirectory; // we need this to check if the basedirectory changes diff --git a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs index 7859f4af..7616c589 100644 --- a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs @@ -15,11 +15,8 @@ namespace Bloxstrap.UI.ViewModels.Menu { - public class ModsViewModel : INotifyPropertyChanged + public class ModsViewModel : NotifyPropertyChangedViewModel { - public event PropertyChangedEventHandler? PropertyChanged; - public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - private void OpenModsFolder() => Process.Start("explorer.exe", Directories.Modifications); private string _customFontLocation = Path.Combine(Directories.Modifications, "content\\fonts\\CustomFont.ttf"); diff --git a/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs b/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs new file mode 100644 index 00000000..54acc1fd --- /dev/null +++ b/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.UI.ViewModels +{ + public class NotifyPropertyChangedViewModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler? PropertyChanged; + public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } +} From 282d4c665a2e8ddea521277d9377b128a37597f1 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 22:52:44 +0100 Subject: [PATCH 102/178] Consolidation - global usings --- Bloxstrap/App.xaml.cs | 20 +----- Bloxstrap/Bootstrapper.cs | 17 +---- Bloxstrap/Directories.cs | 5 +- Bloxstrap/Extensions/BootstrapperIconEx.cs | 5 +- Bloxstrap/Extensions/BootstrapperStyleEx.cs | 5 +- Bloxstrap/Extensions/CursorTypeEx.cs | 6 +- Bloxstrap/Extensions/DateTimeEx.cs | 6 +- Bloxstrap/Extensions/EmojiTypeEx.cs | 6 +- Bloxstrap/Extensions/IconEx.cs | 1 - Bloxstrap/Extensions/ThemeEx.cs | 1 - Bloxstrap/FastFlagManager.cs | 6 +- Bloxstrap/GlobalUsings.cs | 22 +++++++ Bloxstrap/HttpClientLoggingHandler.cs | 11 +--- Bloxstrap/Integrations/DiscordRichPresence.cs | 10 +-- Bloxstrap/Integrations/ServerNotifier.cs | 4 +- Bloxstrap/JsonManager.cs | 6 +- Bloxstrap/Logger.cs | 9 +-- .../Attributes/BuildMetadataAttribute.cs | 4 +- Bloxstrap/Models/ClientVersion.cs | 5 +- Bloxstrap/Models/DeployInfo.cs | 8 +-- Bloxstrap/Models/FontFace.cs | 5 +- Bloxstrap/Models/FontFamily.cs | 5 +- Bloxstrap/Models/GameMessage.cs | 4 +- Bloxstrap/Models/GithubRelease.cs | 5 +- Bloxstrap/Models/PackageManifest.cs | 5 -- .../Models/RobloxApi/ApiArrayResponse.cs | 5 +- Bloxstrap/Models/RobloxApi/GameCreator.cs | 4 +- .../Models/RobloxApi/GameDetailResponse.cs | 6 +- .../Models/RobloxApi/ThumbnailResponse.cs | 4 +- .../Models/RobloxApi/UniverseIdResponse.cs | 4 +- Bloxstrap/Models/Settings.cs | 2 - Bloxstrap/Models/State.cs | 6 +- Bloxstrap/ProtocolHandler.cs | 8 +-- Bloxstrap/Resource.cs | 5 +- Bloxstrap/RobloxActivity.cs | 12 +--- Bloxstrap/RobloxDeployment.cs | 11 +--- Bloxstrap/UI/Controls.cs | 5 +- .../Bootstrapper/Base/BaseFunctions.cs | 3 +- .../Bootstrapper/Base/WinFormsDialogBase.cs | 4 +- .../Bootstrapper/ByfronDialog.xaml.cs | 5 +- .../Bootstrapper/FluentDialog.xaml.cs | 5 +- .../Elements/Bootstrapper/LegacyDialog2008.cs | 1 - .../Elements/Bootstrapper/LegacyDialog2011.cs | 2 - .../Elements/Bootstrapper/ProgressDialog.cs | 5 +- .../UI/Elements/Bootstrapper/VistaDialog.cs | 4 +- Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs | 6 +- .../UI/Elements/FluentMessageBox.xaml.cs | 6 +- Bloxstrap/UI/Elements/Menu/MainWindow.xaml.cs | 4 +- .../Elements/Menu/Pages/BehaviourPage.xaml.cs | 7 +-- .../Elements/Menu/Pages/FastFlagsPage.xaml.cs | 3 +- .../Menu/Pages/IntegrationsPage.xaml.cs | 1 - .../UI/Elements/Menu/Pages/ModsPage.xaml.cs | 3 +- Bloxstrap/UI/IBootstrapperDialog.cs | 3 +- Bloxstrap/UI/Utility/WindowScaling.cs | 3 +- .../BootstrapperDialogViewModel.cs | 5 +- .../Bootstrapper/ByfronDialogViewModel.cs | 6 +- .../UI/ViewModels/Menu/AboutViewModel.cs | 6 +- .../UI/ViewModels/Menu/AppearanceViewModel.cs | 10 +-- .../UI/ViewModels/Menu/BehaviourViewModel.cs | 12 +--- .../UI/ViewModels/Menu/FastFlagsViewModel.cs | 7 +-- .../ViewModels/Menu/InstallationViewModel.cs | 4 +- .../ViewModels/Menu/IntegrationsViewModel.cs | 3 - .../UI/ViewModels/Menu/MainWindowViewModel.cs | 7 +-- Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs | 10 +-- .../NotifyPropertyChangedViewModel.cs | 7 +-- Bloxstrap/Updater.cs | 9 +-- Bloxstrap/Utilities.cs | 6 +- Bloxstrap/Utility/AsyncMutex.cs | 9 +-- Bloxstrap/Utility/Http.cs | 6 +- Bloxstrap/Utility/MD5Hash.cs | 62 +++++++++---------- Bloxstrap/Utility/NativeMethods.cs | 7 +-- Bloxstrap/Utility/SystemEvent.cs | 6 +- 72 files changed, 116 insertions(+), 384 deletions(-) create mode 100644 Bloxstrap/GlobalUsings.cs diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 4e7fb936..907dd8ed 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -1,25 +1,9 @@ -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Net; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; +using System.Reflection; using System.Windows; using System.Windows.Threading; using Microsoft.Win32; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; -using Bloxstrap.Models; -using Bloxstrap.Models.Attributes; -using Bloxstrap.UI; -using Bloxstrap.Utility; - namespace Bloxstrap { /// @@ -27,8 +11,6 @@ namespace Bloxstrap /// public partial class App : Application { - public static readonly CultureInfo CultureFormat = CultureInfo.InvariantCulture; - public const string ProjectName = "Bloxstrap"; public const string ProjectRepository = "pizzaboxer/bloxstrap"; public const string RobloxAppName = "RobloxPlayerBeta"; diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index f9f263f5..b3b359ee 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1,24 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; +using System.Windows; using System.Windows.Forms; -using System.Windows; using Microsoft.Win32; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; using Bloxstrap.Integrations; -using Bloxstrap.Models; -using Bloxstrap.Tools; -using Bloxstrap.UI; namespace Bloxstrap { diff --git a/Bloxstrap/Directories.cs b/Bloxstrap/Directories.cs index faddb26d..21f9d13c 100644 --- a/Bloxstrap/Directories.cs +++ b/Bloxstrap/Directories.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; - -namespace Bloxstrap +namespace Bloxstrap { static class Directories { diff --git a/Bloxstrap/Extensions/BootstrapperIconEx.cs b/Bloxstrap/Extensions/BootstrapperIconEx.cs index dad9cefb..90656a76 100644 --- a/Bloxstrap/Extensions/BootstrapperIconEx.cs +++ b/Bloxstrap/Extensions/BootstrapperIconEx.cs @@ -1,7 +1,4 @@ -using System; -using System.Drawing; - -using Bloxstrap.Enums; +using System.Drawing; namespace Bloxstrap.Extensions { diff --git a/Bloxstrap/Extensions/BootstrapperStyleEx.cs b/Bloxstrap/Extensions/BootstrapperStyleEx.cs index bb837d88..607c6b28 100644 --- a/Bloxstrap/Extensions/BootstrapperStyleEx.cs +++ b/Bloxstrap/Extensions/BootstrapperStyleEx.cs @@ -1,7 +1,4 @@ -using Bloxstrap.Enums; -using Bloxstrap.UI; - -namespace Bloxstrap.Extensions +namespace Bloxstrap.Extensions { static class BootstrapperStyleEx { diff --git a/Bloxstrap/Extensions/CursorTypeEx.cs b/Bloxstrap/Extensions/CursorTypeEx.cs index a46dc7ec..34b8de94 100644 --- a/Bloxstrap/Extensions/CursorTypeEx.cs +++ b/Bloxstrap/Extensions/CursorTypeEx.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; - -using Bloxstrap.Enums; - -namespace Bloxstrap.Extensions +namespace Bloxstrap.Extensions { static class CursorTypeEx { diff --git a/Bloxstrap/Extensions/DateTimeEx.cs b/Bloxstrap/Extensions/DateTimeEx.cs index f30d0115..62b4744d 100644 --- a/Bloxstrap/Extensions/DateTimeEx.cs +++ b/Bloxstrap/Extensions/DateTimeEx.cs @@ -1,12 +1,10 @@ -using System; - -namespace Bloxstrap.Extensions +namespace Bloxstrap.Extensions { static class DateTimeEx { public static string ToFriendlyString(this DateTime dateTime) { - return dateTime.ToString("dddd, d MMMM yyyy 'at' h:mm:ss tt", App.CultureFormat); + return dateTime.ToString("dddd, d MMMM yyyy 'at' h:mm:ss tt"); } } } diff --git a/Bloxstrap/Extensions/EmojiTypeEx.cs b/Bloxstrap/Extensions/EmojiTypeEx.cs index 07fd220e..0eb9d6ea 100644 --- a/Bloxstrap/Extensions/EmojiTypeEx.cs +++ b/Bloxstrap/Extensions/EmojiTypeEx.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; - -using Bloxstrap.Enums; - -namespace Bloxstrap.Extensions +namespace Bloxstrap.Extensions { static class EmojiTypeEx { diff --git a/Bloxstrap/Extensions/IconEx.cs b/Bloxstrap/Extensions/IconEx.cs index bdb1ddd4..2cd48af7 100644 --- a/Bloxstrap/Extensions/IconEx.cs +++ b/Bloxstrap/Extensions/IconEx.cs @@ -1,5 +1,4 @@ using System.Drawing; -using System.IO; using System.Windows.Media.Imaging; using System.Windows.Media; diff --git a/Bloxstrap/Extensions/ThemeEx.cs b/Bloxstrap/Extensions/ThemeEx.cs index 57ab9556..30da5392 100644 --- a/Bloxstrap/Extensions/ThemeEx.cs +++ b/Bloxstrap/Extensions/ThemeEx.cs @@ -1,5 +1,4 @@ using Microsoft.Win32; -using Bloxstrap.Enums; namespace Bloxstrap.Extensions { diff --git a/Bloxstrap/FastFlagManager.cs b/Bloxstrap/FastFlagManager.cs index 0685e864..0043f6e4 100644 --- a/Bloxstrap/FastFlagManager.cs +++ b/Bloxstrap/FastFlagManager.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; -using System.IO; -using System.Text.Json; - -namespace Bloxstrap +namespace Bloxstrap { public class FastFlagManager : JsonManager> { diff --git a/Bloxstrap/GlobalUsings.cs b/Bloxstrap/GlobalUsings.cs new file mode 100644 index 00000000..2bfd51a1 --- /dev/null +++ b/Bloxstrap/GlobalUsings.cs @@ -0,0 +1,22 @@ +global using System; +global using System.Collections.Generic; +global using System.Diagnostics; +global using System.IO; +global using System.IO.Compression; +global using System.Text; +global using System.Text.Json; +global using System.Text.Json.Serialization; +global using System.Text.RegularExpressions; +global using System.Linq; +global using System.Net; +global using System.Net.Http; +global using System.Threading; +global using System.Threading.Tasks; + +global using Bloxstrap.Enums; +global using Bloxstrap.Extensions; +global using Bloxstrap.Models; +global using Bloxstrap.Models.Attributes; +global using Bloxstrap.Models.RobloxApi; +global using Bloxstrap.UI; +global using Bloxstrap.Utility; \ No newline at end of file diff --git a/Bloxstrap/HttpClientLoggingHandler.cs b/Bloxstrap/HttpClientLoggingHandler.cs index ccf7bd28..a39b94ad 100644 --- a/Bloxstrap/HttpClientLoggingHandler.cs +++ b/Bloxstrap/HttpClientLoggingHandler.cs @@ -1,13 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap +namespace Bloxstrap { internal class HttpClientLoggingHandler : MessageProcessingHandler { diff --git a/Bloxstrap/Integrations/DiscordRichPresence.cs b/Bloxstrap/Integrations/DiscordRichPresence.cs index f6d40288..35628d00 100644 --- a/Bloxstrap/Integrations/DiscordRichPresence.cs +++ b/Bloxstrap/Integrations/DiscordRichPresence.cs @@ -1,12 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -using DiscordRPC; - -using Bloxstrap.Models.RobloxApi; -using Bloxstrap.Models; +using DiscordRPC; namespace Bloxstrap.Integrations { diff --git a/Bloxstrap/Integrations/ServerNotifier.cs b/Bloxstrap/Integrations/ServerNotifier.cs index bfd55be3..02e9b6a0 100644 --- a/Bloxstrap/Integrations/ServerNotifier.cs +++ b/Bloxstrap/Integrations/ServerNotifier.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; namespace Bloxstrap.Integrations { diff --git a/Bloxstrap/JsonManager.cs b/Bloxstrap/JsonManager.cs index 095819ab..38baeeec 100644 --- a/Bloxstrap/JsonManager.cs +++ b/Bloxstrap/JsonManager.cs @@ -1,8 +1,4 @@ -using System; -using System.IO; -using System.Text.Json; - -namespace Bloxstrap +namespace Bloxstrap { public class JsonManager where T : new() { diff --git a/Bloxstrap/Logger.cs b/Bloxstrap/Logger.cs index aabc96e0..3ef73ee9 100644 --- a/Bloxstrap/Logger.cs +++ b/Bloxstrap/Logger.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using System.Threading; - -namespace Bloxstrap +namespace Bloxstrap { // https://stackoverflow.com/a/53873141/11852173 // TODO - this kind of sucks diff --git a/Bloxstrap/Models/Attributes/BuildMetadataAttribute.cs b/Bloxstrap/Models/Attributes/BuildMetadataAttribute.cs index 32423f38..7c8fbe09 100644 --- a/Bloxstrap/Models/Attributes/BuildMetadataAttribute.cs +++ b/Bloxstrap/Models/Attributes/BuildMetadataAttribute.cs @@ -1,6 +1,4 @@ -using System; - -namespace Bloxstrap.Models.Attributes +namespace Bloxstrap.Models.Attributes { [AttributeUsage(AttributeTargets.Assembly)] public class BuildMetadataAttribute : Attribute diff --git a/Bloxstrap/Models/ClientVersion.cs b/Bloxstrap/Models/ClientVersion.cs index 4f18c472..e951e4e0 100644 --- a/Bloxstrap/Models/ClientVersion.cs +++ b/Bloxstrap/Models/ClientVersion.cs @@ -1,7 +1,4 @@ -using System; -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class ClientVersion { diff --git a/Bloxstrap/Models/DeployInfo.cs b/Bloxstrap/Models/DeployInfo.cs index 2f8f2651..91c4f944 100644 --- a/Bloxstrap/Models/DeployInfo.cs +++ b/Bloxstrap/Models/DeployInfo.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class DeployInfo { diff --git a/Bloxstrap/Models/FontFace.cs b/Bloxstrap/Models/FontFace.cs index 50bb179c..b8da43ce 100644 --- a/Bloxstrap/Models/FontFace.cs +++ b/Bloxstrap/Models/FontFace.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class FontFace { diff --git a/Bloxstrap/Models/FontFamily.cs b/Bloxstrap/Models/FontFamily.cs index 9a846e1e..1416a8ff 100644 --- a/Bloxstrap/Models/FontFamily.cs +++ b/Bloxstrap/Models/FontFamily.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class FontFamily { diff --git a/Bloxstrap/Models/GameMessage.cs b/Bloxstrap/Models/GameMessage.cs index d7b1b987..7639652a 100644 --- a/Bloxstrap/Models/GameMessage.cs +++ b/Bloxstrap/Models/GameMessage.cs @@ -1,6 +1,4 @@ -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class GameMessage { diff --git a/Bloxstrap/Models/GithubRelease.cs b/Bloxstrap/Models/GithubRelease.cs index a3885862..12b88760 100644 --- a/Bloxstrap/Models/GithubRelease.cs +++ b/Bloxstrap/Models/GithubRelease.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class GithubRelease { diff --git a/Bloxstrap/Models/PackageManifest.cs b/Bloxstrap/Models/PackageManifest.cs index 72eb7999..4d7c3a18 100644 --- a/Bloxstrap/Models/PackageManifest.cs +++ b/Bloxstrap/Models/PackageManifest.cs @@ -4,11 +4,6 @@ * Copyright (c) 2015-present MaximumADHD */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - namespace Bloxstrap.Models { public class PackageManifest : List diff --git a/Bloxstrap/Models/RobloxApi/ApiArrayResponse.cs b/Bloxstrap/Models/RobloxApi/ApiArrayResponse.cs index 7f7e9484..4e1fefdb 100644 --- a/Bloxstrap/Models/RobloxApi/ApiArrayResponse.cs +++ b/Bloxstrap/Models/RobloxApi/ApiArrayResponse.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models.RobloxApi +namespace Bloxstrap.Models.RobloxApi { /// /// Roblox.Web.WebAPI.Models.ApiArrayResponse diff --git a/Bloxstrap/Models/RobloxApi/GameCreator.cs b/Bloxstrap/Models/RobloxApi/GameCreator.cs index 3f4ef22e..c1918844 100644 --- a/Bloxstrap/Models/RobloxApi/GameCreator.cs +++ b/Bloxstrap/Models/RobloxApi/GameCreator.cs @@ -1,6 +1,4 @@ -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models.RobloxApi +namespace Bloxstrap.Models.RobloxApi { /// /// Roblox.Games.Api.Models.Response.GameCreator diff --git a/Bloxstrap/Models/RobloxApi/GameDetailResponse.cs b/Bloxstrap/Models/RobloxApi/GameDetailResponse.cs index 2a824ac9..dca8c814 100644 --- a/Bloxstrap/Models/RobloxApi/GameDetailResponse.cs +++ b/Bloxstrap/Models/RobloxApi/GameDetailResponse.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models.RobloxApi +namespace Bloxstrap.Models.RobloxApi { /// diff --git a/Bloxstrap/Models/RobloxApi/ThumbnailResponse.cs b/Bloxstrap/Models/RobloxApi/ThumbnailResponse.cs index 2a4a2275..c6678132 100644 --- a/Bloxstrap/Models/RobloxApi/ThumbnailResponse.cs +++ b/Bloxstrap/Models/RobloxApi/ThumbnailResponse.cs @@ -1,6 +1,4 @@ -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models.RobloxApi +namespace Bloxstrap.Models.RobloxApi { /// /// Roblox.Web.Responses.Thumbnails.ThumbnailResponse diff --git a/Bloxstrap/Models/RobloxApi/UniverseIdResponse.cs b/Bloxstrap/Models/RobloxApi/UniverseIdResponse.cs index 19bb84d1..c42d10af 100644 --- a/Bloxstrap/Models/RobloxApi/UniverseIdResponse.cs +++ b/Bloxstrap/Models/RobloxApi/UniverseIdResponse.cs @@ -1,6 +1,4 @@ -using System.Text.Json.Serialization; - -namespace Bloxstrap.Models.RobloxApi +namespace Bloxstrap.Models.RobloxApi { // lmao its just one property public class UniverseIdResponse diff --git a/Bloxstrap/Models/Settings.cs b/Bloxstrap/Models/Settings.cs index 95fd18f4..4ba664a1 100644 --- a/Bloxstrap/Models/Settings.cs +++ b/Bloxstrap/Models/Settings.cs @@ -1,7 +1,5 @@ using System.Collections.ObjectModel; -using Bloxstrap.Enums; - namespace Bloxstrap.Models { public class Settings diff --git a/Bloxstrap/Models/State.cs b/Bloxstrap/Models/State.cs index b099001e..0e0a2e82 100644 --- a/Bloxstrap/Models/State.cs +++ b/Bloxstrap/Models/State.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; - -using Bloxstrap.Enums; - -namespace Bloxstrap.Models +namespace Bloxstrap.Models { public class State { diff --git a/Bloxstrap/ProtocolHandler.cs b/Bloxstrap/ProtocolHandler.cs index 4d4c58c1..5d12b12f 100644 --- a/Bloxstrap/ProtocolHandler.cs +++ b/Bloxstrap/ProtocolHandler.cs @@ -1,14 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Web; +using System.Web; using System.Windows; using Microsoft.Win32; -using Bloxstrap.Enums; -using Bloxstrap.UI; - namespace Bloxstrap { static class ProtocolHandler diff --git a/Bloxstrap/Resource.cs b/Bloxstrap/Resource.cs index a5a89bb5..98df7e60 100644 --- a/Bloxstrap/Resource.cs +++ b/Bloxstrap/Resource.cs @@ -1,7 +1,4 @@ -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; +using System.Reflection; namespace Bloxstrap { diff --git a/Bloxstrap/RobloxActivity.cs b/Bloxstrap/RobloxActivity.cs index ca87f3c8..a0e89e27 100644 --- a/Bloxstrap/RobloxActivity.cs +++ b/Bloxstrap/RobloxActivity.cs @@ -1,14 +1,4 @@ -using System; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; - -using Bloxstrap.Models; - -namespace Bloxstrap +namespace Bloxstrap { public class RobloxActivity : IDisposable { diff --git a/Bloxstrap/RobloxDeployment.cs b/Bloxstrap/RobloxDeployment.cs index dc597f1c..6667ca8e 100644 --- a/Bloxstrap/RobloxDeployment.cs +++ b/Bloxstrap/RobloxDeployment.cs @@ -1,13 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading.Tasks; - -using Bloxstrap.Models; - -namespace Bloxstrap +namespace Bloxstrap { public static class RobloxDeployment { diff --git a/Bloxstrap/UI/Controls.cs b/Bloxstrap/UI/Controls.cs index 34115be9..8d7faf85 100644 --- a/Bloxstrap/UI/Controls.cs +++ b/Bloxstrap/UI/Controls.cs @@ -1,8 +1,5 @@ -using System; -using System.Windows; +using System.Windows; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; using Bloxstrap.UI.Elements.Bootstrapper; using Bloxstrap.UI.Menu; using Bloxstrap.UI.MessageBox; diff --git a/Bloxstrap/UI/Elements/Bootstrapper/Base/BaseFunctions.cs b/Bloxstrap/UI/Elements/Bootstrapper/Base/BaseFunctions.cs index c3e3c087..8e493a3b 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/Base/BaseFunctions.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/Base/BaseFunctions.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows; +using System.Windows; namespace Bloxstrap.UI.Elements.Bootstrapper.Base { diff --git a/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs b/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs index 4627a0be..ba14b073 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/Base/WinFormsDialogBase.cs @@ -1,7 +1,5 @@ -using System; -using System.Windows.Forms; +using System.Windows.Forms; -using Bloxstrap.Extensions; using Bloxstrap.UI.Utility; namespace Bloxstrap.UI.Elements.Bootstrapper.Base diff --git a/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs b/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs index a1d73855..88020adb 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/ByfronDialog.xaml.cs @@ -1,11 +1,8 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Forms; using System.Windows.Media; using System.Windows.Media.Imaging; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; using Bloxstrap.UI.Elements.Bootstrapper.Base; using Bloxstrap.UI.ViewModels.Bootstrapper; diff --git a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs index fd3ec5e6..ac3311f0 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml.cs @@ -1,12 +1,9 @@ -using System; -using System.Windows; -using System.Windows.Forms; +using System.Windows.Forms; using Wpf.Ui.Appearance; using Wpf.Ui.Mvvm.Contracts; using Wpf.Ui.Mvvm.Services; -using Bloxstrap.Extensions; using Bloxstrap.UI.ViewModels.Bootstrapper; using Bloxstrap.UI.Elements.Bootstrapper.Base; diff --git a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs index a84042cb..65d5251d 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2008.cs @@ -1,4 +1,3 @@ -using System; using System.Windows.Forms; using Bloxstrap.UI.Elements.Bootstrapper.Base; diff --git a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2011.cs b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2011.cs index ae7657b2..0588675a 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2011.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/LegacyDialog2011.cs @@ -1,7 +1,5 @@ -using System; using System.Windows.Forms; -using Bloxstrap.Extensions; using Bloxstrap.UI.Elements.Bootstrapper.Base; namespace Bloxstrap.UI.Elements.Bootstrapper diff --git a/Bloxstrap/UI/Elements/Bootstrapper/ProgressDialog.cs b/Bloxstrap/UI/Elements/Bootstrapper/ProgressDialog.cs index 8773d766..4f9bb01b 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/ProgressDialog.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/ProgressDialog.cs @@ -1,9 +1,6 @@ -using System; -using System.Drawing; +using System.Drawing; using System.Windows.Forms; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; using Bloxstrap.UI.Elements.Bootstrapper.Base; namespace Bloxstrap.UI.Elements.Bootstrapper diff --git a/Bloxstrap/UI/Elements/Bootstrapper/VistaDialog.cs b/Bloxstrap/UI/Elements/Bootstrapper/VistaDialog.cs index f102ad03..8a47f9cf 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/VistaDialog.cs +++ b/Bloxstrap/UI/Elements/Bootstrapper/VistaDialog.cs @@ -1,7 +1,5 @@ -using System; -using System.Windows.Forms; +using System.Windows.Forms; -using Bloxstrap.Extensions; using Bloxstrap.UI.Elements.Bootstrapper.Base; namespace Bloxstrap.UI.Elements.Bootstrapper diff --git a/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs b/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs index 2b71bcb7..6c071944 100644 --- a/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs +++ b/Bloxstrap/UI/Elements/ExceptionDialog.xaml.cs @@ -1,11 +1,7 @@ -using System; -using System.Diagnostics; -using System.Media; +using System.Media; using System.Windows; using System.Windows.Interop; -using Bloxstrap.Utility; - namespace Bloxstrap.UI { // hmm... do i use MVVM for this? diff --git a/Bloxstrap/UI/Elements/FluentMessageBox.xaml.cs b/Bloxstrap/UI/Elements/FluentMessageBox.xaml.cs index c04e178a..19157f62 100644 --- a/Bloxstrap/UI/Elements/FluentMessageBox.xaml.cs +++ b/Bloxstrap/UI/Elements/FluentMessageBox.xaml.cs @@ -1,12 +1,10 @@ -using System; -using System.Configuration; -using System.Media; +using System.Media; using System.Windows; using System.Windows.Controls; using System.Windows.Interop; using System.Windows.Media.Imaging; + using Bloxstrap.UI.Utility; -using Bloxstrap.Utility; namespace Bloxstrap.UI.MessageBox { diff --git a/Bloxstrap/UI/Elements/Menu/MainWindow.xaml.cs b/Bloxstrap/UI/Elements/Menu/MainWindow.xaml.cs index 65fed5ef..d974e529 100644 --- a/Bloxstrap/UI/Elements/Menu/MainWindow.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/MainWindow.xaml.cs @@ -1,12 +1,10 @@ -using System; -using System.Windows.Controls; +using System.Windows.Controls; using Wpf.Ui.Appearance; using Wpf.Ui.Controls.Interfaces; using Wpf.Ui.Mvvm.Contracts; using Wpf.Ui.Mvvm.Services; -using Bloxstrap.Extensions; using Bloxstrap.UI.ViewModels.Menu; namespace Bloxstrap.UI.Menu diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs index 736197b7..f423e1b9 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs @@ -1,9 +1,4 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Input; - -using Bloxstrap.UI.ViewModels.Menu; +using Bloxstrap.UI.ViewModels.Menu; namespace Bloxstrap.UI.Menu.Pages { diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs index 7770a97b..ccf4cff2 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows.Input; +using System.Windows.Input; using Bloxstrap.UI.ViewModels.Menu; diff --git a/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml.cs index 397aeca1..9210778b 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml.cs @@ -1,6 +1,5 @@ using System.Windows.Controls; -using Bloxstrap.Models; using Bloxstrap.UI.ViewModels.Menu; namespace Bloxstrap.UI.Menu.Pages diff --git a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml.cs index 50cece0c..c3173d2e 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows; +using System.Windows; using Bloxstrap.UI.ViewModels.Menu; diff --git a/Bloxstrap/UI/IBootstrapperDialog.cs b/Bloxstrap/UI/IBootstrapperDialog.cs index 26b5aeeb..4b449007 100644 --- a/Bloxstrap/UI/IBootstrapperDialog.cs +++ b/Bloxstrap/UI/IBootstrapperDialog.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows.Forms; +using System.Windows.Forms; namespace Bloxstrap.UI { diff --git a/Bloxstrap/UI/Utility/WindowScaling.cs b/Bloxstrap/UI/Utility/WindowScaling.cs index 8ede97a1..91447ad9 100644 --- a/Bloxstrap/UI/Utility/WindowScaling.cs +++ b/Bloxstrap/UI/Utility/WindowScaling.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Forms; namespace Bloxstrap.UI.Utility diff --git a/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs b/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs index 5867d5c4..593921de 100644 --- a/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Bootstrapper/BootstrapperDialogViewModel.cs @@ -1,12 +1,9 @@ -using System.ComponentModel; -using System.Windows; +using System.Windows; using System.Windows.Input; using System.Windows.Media; using CommunityToolkit.Mvvm.Input; -using Bloxstrap.Extensions; - namespace Bloxstrap.UI.ViewModels.Bootstrapper { public class BootstrapperDialogViewModel : NotifyPropertyChangedViewModel diff --git a/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs b/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs index 568fe34b..29eb85a5 100644 --- a/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Bootstrapper/ByfronDialogViewModel.cs @@ -1,8 +1,4 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Windows; +using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; diff --git a/Bloxstrap/UI/ViewModels/Menu/AboutViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/AboutViewModel.cs index 8291e121..5222f27c 100644 --- a/Bloxstrap/UI/ViewModels/Menu/AboutViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/AboutViewModel.cs @@ -1,8 +1,4 @@ -using System; -using System.Windows; - -using Bloxstrap.Extensions; -using Bloxstrap.Models.Attributes; +using System.Windows; namespace Bloxstrap.UI.ViewModels.Menu { diff --git a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs index 19a5224b..d81edfcd 100644 --- a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs @@ -1,16 +1,12 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Windows; +using System.Windows; using System.Windows.Controls; -using Microsoft.Win32; using System.Windows.Input; using System.Windows.Media; using CommunityToolkit.Mvvm.Input; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; +using Microsoft.Win32; + using Bloxstrap.UI.Menu; namespace Bloxstrap.UI.ViewModels.Menu diff --git a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs index 07688194..38b1a192 100644 --- a/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/BehaviourViewModel.cs @@ -1,14 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; - - -using Bloxstrap.Enums; -using Bloxstrap.Extensions; -using Bloxstrap.Models; +using System.Windows; namespace Bloxstrap.UI.ViewModels.Menu { diff --git a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs index 30ea3703..3ba02f61 100644 --- a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Windows; +using System.Windows; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; diff --git a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs index 389abe84..c00093c2 100644 --- a/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel; -using System.Diagnostics; -using System.Windows.Input; +using System.Windows.Input; using CommunityToolkit.Mvvm.Input; diff --git a/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs index d0425ac6..640b8b84 100644 --- a/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/IntegrationsViewModel.cs @@ -1,11 +1,8 @@ using System.Collections.ObjectModel; -using System.ComponentModel; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; -using Bloxstrap.Models; - namespace Bloxstrap.UI.ViewModels.Menu { public class IntegrationsViewModel : NotifyPropertyChangedViewModel diff --git a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs index cad2e8d9..9e51a3a3 100644 --- a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; using System.Windows.Input; using Microsoft.Win32; diff --git a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs index 7616c589..3502350d 100644 --- a/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/ModsViewModel.cs @@ -1,14 +1,6 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Windows; +using System.Windows; using System.Windows.Input; -using Bloxstrap.Enums; -using Bloxstrap.Extensions; - using Microsoft.Win32; using CommunityToolkit.Mvvm.Input; diff --git a/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs b/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs index 54acc1fd..6cf587b8 100644 --- a/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs +++ b/Bloxstrap/UI/ViewModels/NotifyPropertyChangedViewModel.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel; namespace Bloxstrap.UI.ViewModels { diff --git a/Bloxstrap/Updater.cs b/Bloxstrap/Updater.cs index b438634d..39434e18 100644 --- a/Bloxstrap/Updater.cs +++ b/Bloxstrap/Updater.cs @@ -1,11 +1,4 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Windows; -using System.Threading; -using System.Threading.Tasks; - -using Bloxstrap.UI; +using System.Windows; namespace Bloxstrap { diff --git a/Bloxstrap/Utilities.cs b/Bloxstrap/Utilities.cs index 32194fad..c362a710 100644 --- a/Bloxstrap/Utilities.cs +++ b/Bloxstrap/Utilities.cs @@ -1,8 +1,4 @@ -using System; -using System.Diagnostics; -using System.IO; - -namespace Bloxstrap +namespace Bloxstrap { static class Utilities { diff --git a/Bloxstrap/Utility/AsyncMutex.cs b/Bloxstrap/Utility/AsyncMutex.cs index e6e972f9..400ccc89 100644 --- a/Bloxstrap/Utility/AsyncMutex.cs +++ b/Bloxstrap/Utility/AsyncMutex.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap.Tools +namespace Bloxstrap.Utility { // https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e diff --git a/Bloxstrap/Utility/Http.cs b/Bloxstrap/Utility/Http.cs index dbdec6bd..3d1f402d 100644 --- a/Bloxstrap/Utility/Http.cs +++ b/Bloxstrap/Utility/Http.cs @@ -1,8 +1,4 @@ -using System; -using System.Text.Json; -using System.Threading.Tasks; - -namespace Bloxstrap.Utility +namespace Bloxstrap.Utility { internal static class Http { diff --git a/Bloxstrap/Utility/MD5Hash.cs b/Bloxstrap/Utility/MD5Hash.cs index 9e1abcb9..caa7e48a 100644 --- a/Bloxstrap/Utility/MD5Hash.cs +++ b/Bloxstrap/Utility/MD5Hash.cs @@ -1,34 +1,28 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace Bloxstrap.Utility -{ - public static class MD5Hash - { - public static string FromFile(string filename) - { - using (MD5 md5 = MD5.Create()) - { - using (FileStream stream = File.OpenRead(filename)) - { - byte[] hash = md5.ComputeHash(stream); - return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - } - } - } - - public static string FromBytes(byte[] data) - { - using (MD5 md5 = MD5.Create()) - { - byte[] hash = md5.ComputeHash(data); - return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - } - } - } -} +using System.Security.Cryptography; + +namespace Bloxstrap.Utility +{ + public static class MD5Hash + { + public static string FromFile(string filename) + { + using (MD5 md5 = MD5.Create()) + { + using (FileStream stream = File.OpenRead(filename)) + { + byte[] hash = md5.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } + + public static string FromBytes(byte[] data) + { + using (MD5 md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(data); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } +} diff --git a/Bloxstrap/Utility/NativeMethods.cs b/Bloxstrap/Utility/NativeMethods.cs index 76cbbb65..321fbcfd 100644 --- a/Bloxstrap/Utility/NativeMethods.cs +++ b/Bloxstrap/Utility/NativeMethods.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.InteropServices; namespace Bloxstrap.Utility { diff --git a/Bloxstrap/Utility/SystemEvent.cs b/Bloxstrap/Utility/SystemEvent.cs index 05eb590c..f4b47468 100644 --- a/Bloxstrap/Utility/SystemEvent.cs +++ b/Bloxstrap/Utility/SystemEvent.cs @@ -4,11 +4,7 @@ * Copyright (c) 2015-present MaximumADHD */ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap.Tools +namespace Bloxstrap.Utility { public class SystemEvent : EventWaitHandle { From 0f1dd35efa8b94a3534c45a8b195fc6577607319 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 15 Jul 2023 23:10:52 +0100 Subject: [PATCH 103/178] Enable DPI scaling fixes by default --- Bloxstrap/FastFlagManager.cs | 2 ++ Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/FastFlagManager.cs b/Bloxstrap/FastFlagManager.cs index 0043f6e4..197fd75d 100644 --- a/Bloxstrap/FastFlagManager.cs +++ b/Bloxstrap/FastFlagManager.cs @@ -131,6 +131,8 @@ public override void Load() // set to 9999 by default if it doesnt already exist SetValueOnce("DFIntTaskSchedulerTargetFps", 9999); SetValueOnce("FFlagHandleAltEnterFullscreenManually", "False"); + SetValueOnce("DFFlagDisableDPIScale", "True"); + SetValueOnce("DFFlagVariableDPIScale2", "False"); } public override void Save() diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml index 5a49eaf1..54ac918a 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml @@ -73,11 +73,12 @@ + - + @@ -95,7 +96,7 @@ - + From 1a084015d32432a78bfd8da072ab895b31cb83c8 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Sun, 16 Jul 2023 13:47:45 +0100 Subject: [PATCH 104/178] fix warning without disabling warning --- Bloxstrap/App.xaml.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 907dd8ed..fd65e2eb 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -71,16 +71,14 @@ void GlobalExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs void FinalizeExceptionHandling(Exception exception) { -#pragma warning disable 162 #if DEBUG throw exception; -#endif - +#else if (!IsQuiet) Controls.ShowExceptionDialog(exception); Terminate(ErrorCode.ERROR_INSTALL_FAILURE); -#pragma warning restore 162 +#endif } protected override void OnStartup(StartupEventArgs e) From 8831786d80be82667e6a5e8930aea14c9bda51f5 Mon Sep 17 00:00:00 2001 From: bluepilledgreat <97983689+bluepilledgreat@users.noreply.github.com> Date: Sun, 16 Jul 2023 14:13:51 +0100 Subject: [PATCH 105/178] fix fluent cancel button --- Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml index 5916c073..eb8b10de 100644 --- a/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml +++ b/Bloxstrap/UI/Elements/Bootstrapper/FluentDialog.xaml @@ -38,7 +38,7 @@ - public partial class LogTracer { - private readonly LogTracerViewModel _viewModel; + private bool _autoscroll = true; public LogTracer(RobloxActivity activityWatcher) { - _viewModel = new LogTracerViewModel(this, activityWatcher); - DataContext = _viewModel; - + DataContext = new LogTracerViewModel(this, activityWatcher); InitializeComponent(); } - private void RichTextBox_TextChanged(object sender, TextChangedEventArgs e) => ScrollViewer.ScrollToEnd(); + private void KeepOnTopMenuItem_Click(object sender, RoutedEventArgs e) => Topmost = ((MenuItem)sender).IsChecked; + + private void AutoScrollMenuItem_Click(object sender, RoutedEventArgs e) => _autoscroll = ((MenuItem)sender).IsChecked; + + private void TextBox_TextChanged(object sender, TextChangedEventArgs e) + { + if (_autoscroll) + ScrollViewer.ScrollToEnd(); + } } } diff --git a/Bloxstrap/UI/ViewModels/ContextMenu/LogTracerViewModel.cs b/Bloxstrap/UI/ViewModels/ContextMenu/LogTracerViewModel.cs index 40fc1799..cb398b13 100644 --- a/Bloxstrap/UI/ViewModels/ContextMenu/LogTracerViewModel.cs +++ b/Bloxstrap/UI/ViewModels/ContextMenu/LogTracerViewModel.cs @@ -9,10 +9,12 @@ internal class LogTracerViewModel : NotifyPropertyChangedViewModel { private readonly Window _window; private readonly RobloxActivity _activityWatcher; + private int _lineNumber = 1; public ICommand CloseWindowCommand => new RelayCommand(_window.Close); + public ICommand LocateLogFileCommand => new RelayCommand(LocateLogFile); - public string LogLocation => _activityWatcher.LogFilename; + public string LogFilename => Path.GetFileName(_activityWatcher.LogLocation); public string LogContents { get; private set; } = ""; public LogTracerViewModel(Window window, RobloxActivity activityWatcher) @@ -22,9 +24,13 @@ public LogTracerViewModel(Window window, RobloxActivity activityWatcher) _activityWatcher.OnLogEntry += (_, message) => { - LogContents += message += "\r\n"; + LogContents += $"{_lineNumber}: {message}\r\n"; OnPropertyChanged(nameof(LogContents)); + + _lineNumber += 1; }; } + + private void LocateLogFile() => Process.Start("explorer.exe", $"/select,\"{_activityWatcher.LogLocation}\""); } } From cefe7cd22a1a5b1b9911ca324ac0f3a21b75a948 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 22 Jul 2023 12:18:55 +0100 Subject: [PATCH 134/178] Silently fail when making desktop shortcut (#410) --- Bloxstrap/Bootstrapper.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 8fc9475d..163aa00d 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -454,7 +454,7 @@ private void CheckInstallMigration() public static void CheckInstall() { - App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); + App.Logger.WriteLine("[Bootstrapper::CheckInstall] Checking install"); // check if launch uri is set to our bootstrapper // this doesn't go under register, so we check every launch @@ -502,8 +502,16 @@ public static void CheckInstall() { if (!File.Exists(DesktopShortcutLocation)) { - ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) - .WriteToFile(DesktopShortcutLocation); + try + { + ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) + .WriteToFile(DesktopShortcutLocation); + } + catch (Exception ex) + { + App.Logger.WriteLine("[Bootstrapper::CheckInstall] Could not create desktop shortcut, aborting"); + App.Logger.WriteLine($"[Bootstrapper::CheckInstall] {ex}"); + } } // one-time toggle, set it back to false From 61255925e61dd6124b06b072bb0bfbb2ee160ec9 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 22 Jul 2023 12:32:11 +0100 Subject: [PATCH 135/178] Mitigate rich presence race condition (#411) --- Bloxstrap/Integrations/DiscordRichPresence.cs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Bloxstrap/Integrations/DiscordRichPresence.cs b/Bloxstrap/Integrations/DiscordRichPresence.cs index caf4dfac..b5b32483 100644 --- a/Bloxstrap/Integrations/DiscordRichPresence.cs +++ b/Bloxstrap/Integrations/DiscordRichPresence.cs @@ -25,7 +25,7 @@ public DiscordRichPresence(RobloxActivity activityWatcher) App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Received ready from user {e.User.Username} ({e.User.ID})"); _rpcClient.OnPresenceUpdate += (_, e) => - App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Updated presence"); + App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Presence updated"); _rpcClient.OnError += (_, e) => App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] An RPC error occurred - {e.Message}"); @@ -114,10 +114,11 @@ public async Task SetCurrentGame() } string icon = "roblox"; + long placeId = _activityWatcher.ActivityPlaceId; - App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Setting presence for Place ID {_activityWatcher.ActivityPlaceId}"); + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Setting presence for Place ID {placeId}"); - var universeIdResponse = await Http.GetJson($"https://apis.roblox.com/universes/v1/places/{_activityWatcher.ActivityPlaceId}/universe"); + var universeIdResponse = await Http.GetJson($"https://apis.roblox.com/universes/v1/places/{placeId}/universe"); if (universeIdResponse is null) { App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Could not get Universe ID!"); @@ -159,7 +160,7 @@ public async Task SetCurrentGame() new Button { Label = "See Details", - Url = $"https://www.roblox.com/games/{_activityWatcher.ActivityPlaceId}" + Url = $"https://www.roblox.com/games/{placeId}" } }; @@ -168,7 +169,7 @@ public async Task SetCurrentGame() buttons.Insert(0, new Button { Label = "Join", - Url = $"roblox://experiences/start?placeId={_activityWatcher.ActivityPlaceId}&gameInstanceId={_activityWatcher.ActivityJobId}" + Url = $"roblox://experiences/start?placeId={placeId}&gameInstanceId={_activityWatcher.ActivityJobId}" }); } @@ -176,6 +177,12 @@ public async Task SetCurrentGame() if (universeDetails.Name.Length < 2) universeDetails.Name = $"{universeDetails.Name}\x2800\x2800\x2800"; + if (!_activityWatcher.ActivityInGame || placeId != _activityWatcher.ActivityPlaceId) + { + App.Logger.WriteLine($"[DiscordRichPresence::SetCurrentGame] Aborting presence set because game activity has changed"); + return false; + } + _currentPresence = new RichPresence { Details = universeDetails.Name, @@ -198,8 +205,6 @@ public async Task SetCurrentGame() public void UpdatePresence() { - App.Logger.WriteLine($"[DiscordRichPresence::UpdatePresence] Updating presence"); - if (_currentPresence is null) { App.Logger.WriteLine($"[DiscordRichPresence::UpdatePresence] Presence is empty, clearing"); @@ -207,6 +212,8 @@ public void UpdatePresence() return; } + App.Logger.WriteLine($"[DiscordRichPresence::UpdatePresence] Updating presence"); + if (_visible) _rpcClient.SetPresence(_currentPresence); } @@ -216,6 +223,7 @@ public void Dispose() App.Logger.WriteLine("[DiscordRichPresence::Dispose] Cleaning up Discord RPC and Presence"); _rpcClient.ClearPresence(); _rpcClient.Dispose(); + GC.SuppressFinalize(this); } } } From 049b3408232dee07ddbeccfec0f75a6570e82131 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 22 Jul 2023 13:18:31 +0100 Subject: [PATCH 136/178] Fix UI namespaces --- Bloxstrap/UI/Controls.cs | 4 ++-- Bloxstrap/UI/Elements/{ => Dialogs}/ExceptionDialog.xaml | 4 ++-- Bloxstrap/UI/Elements/{ => Dialogs}/ExceptionDialog.xaml.cs | 2 +- Bloxstrap/UI/Elements/{ => Dialogs}/FluentMessageBox.xaml | 4 ++-- Bloxstrap/UI/Elements/{ => Dialogs}/FluentMessageBox.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/MainWindow.xaml | 4 ++-- Bloxstrap/UI/Elements/Menu/MainWindow.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/AppearancePage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/AppearancePage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml.cs | 2 +- Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml | 2 +- Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml.cs | 2 +- Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs | 2 +- Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs | 2 +- 25 files changed, 29 insertions(+), 29 deletions(-) rename Bloxstrap/UI/Elements/{ => Dialogs}/ExceptionDialog.xaml (95%) rename Bloxstrap/UI/Elements/{ => Dialogs}/ExceptionDialog.xaml.cs (98%) rename Bloxstrap/UI/Elements/{ => Dialogs}/FluentMessageBox.xaml (94%) rename Bloxstrap/UI/Elements/{ => Dialogs}/FluentMessageBox.xaml.cs (99%) diff --git a/Bloxstrap/UI/Controls.cs b/Bloxstrap/UI/Controls.cs index 8d7faf85..bb42bfe4 100644 --- a/Bloxstrap/UI/Controls.cs +++ b/Bloxstrap/UI/Controls.cs @@ -1,8 +1,8 @@ using System.Windows; using Bloxstrap.UI.Elements.Bootstrapper; -using Bloxstrap.UI.Menu; -using Bloxstrap.UI.MessageBox; +using Bloxstrap.UI.Elements.Dialogs; +using Bloxstrap.UI.Elements.Menu; namespace Bloxstrap.UI { diff --git a/Bloxstrap/UI/Elements/ExceptionDialog.xaml b/Bloxstrap/UI/Elements/Dialogs/ExceptionDialog.xaml similarity index 95% rename from Bloxstrap/UI/Elements/ExceptionDialog.xaml rename to Bloxstrap/UI/Elements/Dialogs/ExceptionDialog.xaml index 218142e5..54d8a51f 100644 --- a/Bloxstrap/UI/Elements/ExceptionDialog.xaml +++ b/Bloxstrap/UI/Elements/Dialogs/ExceptionDialog.xaml @@ -1,10 +1,10 @@ - /// Interaction logic for MainWindow.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml index 2c6de52b..1c082302 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for AboutPage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/AppearancePage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/AppearancePage.xaml index 2afbfb52..ff7460aa 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/AppearancePage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/AppearancePage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for AppearancePage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml index c18bfb8f..3b271082 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/BehaviourPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for BehaviourPage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml index c60348a0..26fba4e1 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for FastFlagsPage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml index 24997736..7f285030 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/InstallationPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for InstallationPage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml index 293ea574..f0bcc466 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for IntegrationsPage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml index 37f0bfd5..51727ffc 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/ModsPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for ModsPage.xaml diff --git a/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml index 6b174dad..e253faa0 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for PreInstallPage.xaml diff --git a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs index d81edfcd..cb81afaa 100644 --- a/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/AppearanceViewModel.cs @@ -7,7 +7,7 @@ using Microsoft.Win32; -using Bloxstrap.UI.Menu; +using Bloxstrap.UI.Elements.Menu; namespace Bloxstrap.UI.ViewModels.Menu { diff --git a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs index 9e51a3a3..613240b8 100644 --- a/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs @@ -7,7 +7,7 @@ using Wpf.Ui.Mvvm.Contracts; -using Bloxstrap.UI.Menu.Pages; +using Bloxstrap.UI.Elements.Menu.Pages; namespace Bloxstrap.UI.ViewModels.Menu { From cc39ee6e8a95d474daddc858b2933780ec8032c6 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sat, 22 Jul 2023 22:36:00 +0100 Subject: [PATCH 137/178] Graphical FastFlag editor - initial prototype --- Bloxstrap/Models/FastFlag.cs | 15 ++ .../Elements/Dialogs/AddFastFlagDialog.xaml | 60 ++++++++ .../Dialogs/AddFastFlagDialog.xaml.cs | 35 +++++ Bloxstrap/UI/Elements/Menu/MainWindow.xaml | 1 + .../Menu/Pages/FastFlagEditorPage.xaml | 44 ++++++ .../Menu/Pages/FastFlagEditorPage.xaml.cs | 142 ++++++++++++++++++ .../UI/Elements/Menu/Pages/FastFlagsPage.xaml | 3 +- .../Elements/Menu/Pages/FastFlagsPage.xaml.cs | 9 +- 8 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 Bloxstrap/Models/FastFlag.cs create mode 100644 Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml create mode 100644 Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml.cs create mode 100644 Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml create mode 100644 Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs diff --git a/Bloxstrap/Models/FastFlag.cs b/Bloxstrap/Models/FastFlag.cs new file mode 100644 index 00000000..1f5888a9 --- /dev/null +++ b/Bloxstrap/Models/FastFlag.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.Models +{ + public class FastFlag + { + public bool Enabled { get; set; } + public string Name { get; set; } = null!; + public string Value { get; set; } = null!; + } +} diff --git a/Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml b/Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml new file mode 100644 index 00000000..06e7cc08 --- /dev/null +++ b/Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public partial class FastFlagsPage { + bool _initialLoad = false; + public FastFlagsPage() { + DataContext = new FastFlagsViewModel(); InitializeComponent(); } private void Page_Loaded(object sender, RoutedEventArgs e) { // refresh datacontext on page load to synchronize with editor page + + if (!_initialLoad) + { + _initialLoad = true; + return; + } + DataContext = new FastFlagsViewModel(); } From 0d17cb5b3da69a4ed1ce2aec3750a0fb9c235259 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 17:34:14 +0100 Subject: [PATCH 144/178] Style DataGrid for FastFlag editor god damn i actually managed to make it look GOOD --- .../Menu/Pages/FastFlagEditorPage.xaml | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml index 6d730c9e..6bf9d6d2 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml @@ -18,13 +18,50 @@ - - - + + + + + + + + + + + + + + + - - - + + + From 1b3049fbdbabcc7fc52e620ddfb7678a93e4b5dc Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 17:39:46 +0100 Subject: [PATCH 145/178] Make FastFlag editor state consistent with reloads --- .../Elements/Menu/Pages/FastFlagEditorPage.xaml.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index 2bee58a4..bb2f059b 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -16,13 +16,14 @@ public partial class FastFlagEditorPage // using a datagrid is a codebehind thing only and thats it theres literally no way around it private readonly ObservableCollection _fastFlagList = new(); + private bool _showPresets = false; public FastFlagEditorPage() { InitializeComponent(); } - private void ReloadList(bool showPresets = false) + private void ReloadList() { _fastFlagList.Clear(); @@ -30,7 +31,7 @@ private void ReloadList(bool showPresets = false) foreach (var pair in App.FastFlags.Prop) { - if (!showPresets && presetFlags.Contains(pair.Key)) + if (!_showPresets && presetFlags.Contains(pair.Key)) continue; var entry = new FastFlag @@ -131,8 +132,11 @@ private void DeleteButton_Click(object sender, RoutedEventArgs e) private void ToggleButton_Click(object sender, RoutedEventArgs e) { - if (sender is ToggleButton button) - ReloadList(button.IsChecked ?? false); + if (sender is not ToggleButton button) + return; + + _showPresets = button.IsChecked ?? false; + ReloadList(); } } } From 500b21d601b75e5ca51853ecb9416d40b3d9a93d Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 18:03:53 +0100 Subject: [PATCH 146/178] Remove option to enable/disable flags :( --- Bloxstrap/Models/FastFlag.cs | 15 ----- .../Menu/Pages/FastFlagEditorPage.xaml | 26 ++++----- .../Menu/Pages/FastFlagEditorPage.xaml.cs | 58 ++++--------------- 3 files changed, 25 insertions(+), 74 deletions(-) delete mode 100644 Bloxstrap/Models/FastFlag.cs diff --git a/Bloxstrap/Models/FastFlag.cs b/Bloxstrap/Models/FastFlag.cs deleted file mode 100644 index 1f5888a9..00000000 --- a/Bloxstrap/Models/FastFlag.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Bloxstrap.Models -{ - public class FastFlag - { - public bool Enabled { get; set; } - public string Name { get; set; } = null!; - public string Value { get; set; } = null!; - } -} diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml index 6bf9d6d2..e19a7290 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml @@ -18,15 +18,15 @@ - - - - + - + - + - + - + - - - + + - - + + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index bb2f059b..68e76ecb 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -15,7 +15,7 @@ public partial class FastFlagEditorPage // believe me when i say there is absolutely zero point to using mvvm for this // using a datagrid is a codebehind thing only and thats it theres literally no way around it - private readonly ObservableCollection _fastFlagList = new(); + private readonly ObservableCollection> _fastFlagList = new(); private bool _showPresets = false; public FastFlagEditorPage() @@ -29,24 +29,11 @@ private void ReloadList() var presetFlags = FastFlagManager.PresetFlags.Values; - foreach (var pair in App.FastFlags.Prop) + foreach (var entry in App.FastFlags.Prop) { - if (!_showPresets && presetFlags.Contains(pair.Key)) + if (!_showPresets && presetFlags.Contains(entry.Key)) continue; - var entry = new FastFlag - { - Enabled = true, - Name = pair.Key, - Value = pair.Value - }; - - if (entry.Name.StartsWith("Disable")) - { - entry.Enabled = false; - entry.Name = entry.Name[7..]; - } - _fastFlagList.Add(entry); } @@ -59,30 +46,14 @@ private void ReloadList() private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { int index = e.Row.GetIndex(); - FastFlag entry = _fastFlagList[index]; + var entry = _fastFlagList[index]; switch (e.Column.Header) { - case "Enabled": - bool enabled = (bool)((CheckBox)e.EditingElement).IsChecked!; - - if (enabled) - { - App.FastFlags.SetValue(entry.Name, entry.Value); - App.FastFlags.SetValue($"Disable{entry.Name}", null); - } - else - { - App.FastFlags.SetValue(entry.Name, null); - App.FastFlags.SetValue($"Disable{entry.Name}", entry.Value); - } - - break; - case "Name": string newName = ((TextBox)e.EditingElement).Text; - App.FastFlags.SetValue(entry.Name, null); + App.FastFlags.SetValue(entry.Key, null); App.FastFlags.SetValue(newName, entry.Value); break; @@ -90,7 +61,7 @@ private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventA case "Value": string newValue = ((TextBox)e.EditingElement).Text; - App.FastFlags.SetValue(entry.Name, newValue); + App.FastFlags.SetValue(entry.Key, newValue); break; } @@ -104,29 +75,24 @@ private void AddButton_Click(object sender, RoutedEventArgs e) if (dialog.Result != MessageBoxResult.OK) return; - var entry = new FastFlag - { - Enabled = true, - Name = dialog.FlagNameTextBox.Text, - Value = dialog.FlagValueTextBox.Text - }; + var entry = new KeyValuePair(dialog.FlagNameTextBox.Text, dialog.FlagValueTextBox.Text); _fastFlagList.Add(entry); - App.FastFlags.SetValue(entry.Name, entry.Value); + App.FastFlags.SetValue(entry.Key, entry.Value); } private void DeleteButton_Click(object sender, RoutedEventArgs e) { - var tempList = new List(); + var tempList = new List>(); - foreach (FastFlag entry in DataGrid.SelectedItems) + foreach (KeyValuePair entry in DataGrid.SelectedItems) tempList.Add(entry); - foreach (FastFlag entry in tempList) + foreach (var entry in tempList) { _fastFlagList.Remove(entry); - App.FastFlags.SetValue(entry.Name, null); + App.FastFlags.SetValue(entry.Key, null); } } From b3b174ed4b30d7bd42dfe79163f81f8a797e6edb Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 18:17:34 +0100 Subject: [PATCH 147/178] Finalize placement of flag editor in menu --- Bloxstrap/UI/Elements/Menu/MainWindow.xaml | 4 +- .../Menu/Pages/FastFlagEditorPage.xaml | 37 ++++++++++--------- .../Menu/Pages/FastFlagEditorPage.xaml.cs | 8 ++++ .../UI/Elements/Menu/Pages/FastFlagsPage.xaml | 30 ++------------- .../Elements/Menu/Pages/FastFlagsPage.xaml.cs | 4 +- .../UI/ViewModels/Menu/FastFlagsViewModel.cs | 20 +++++++++- 6 files changed, 53 insertions(+), 50 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/MainWindow.xaml b/Bloxstrap/UI/Elements/Menu/MainWindow.xaml index 013d1eef..73260ad1 100644 --- a/Bloxstrap/UI/Elements/Menu/MainWindow.xaml +++ b/Bloxstrap/UI/Elements/Menu/MainWindow.xaml @@ -43,9 +43,9 @@ - + + - diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml index e19a7290..03cb28b0 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml @@ -12,13 +12,30 @@ - + - + + + + + + + + + + + + - - - - diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index 68e76ecb..3d4c3baf 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -3,6 +3,8 @@ using System.Windows.Controls; using System.Windows.Controls.Primitives; +using Wpf.Ui.Mvvm.Contracts; + using Bloxstrap.UI.Elements.Dialogs; namespace Bloxstrap.UI.Elements.Menu.Pages @@ -67,6 +69,12 @@ private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventA } } + private void BackButton_Click(object sender, RoutedEventArgs e) + { + if (Window.GetWindow(this) is INavigationWindow window) + window.Navigate(typeof(FastFlagsPage)); + } + private void AddButton_Click(object sender, RoutedEventArgs e) { var dialog = new AddFastFlagDialog(); diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml index b7c24914..e6940efc 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml @@ -15,36 +15,14 @@ - + - + - - - - - - - - - - - + + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs index ee3c53ea..d6c8f5bb 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml.cs @@ -14,7 +14,7 @@ public partial class FastFlagsPage public FastFlagsPage() { - DataContext = new FastFlagsViewModel(); + DataContext = new FastFlagsViewModel(this); InitializeComponent(); } @@ -28,7 +28,7 @@ private void Page_Loaded(object sender, RoutedEventArgs e) return; } - DataContext = new FastFlagsViewModel(); + DataContext = new FastFlagsViewModel(this); } private void ValidateInt32(object sender, TextCompositionEventArgs e) => e.Handled = !Int32.TryParse(e.Text, out int _); diff --git a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs index ca32a4fc..3412a308 100644 --- a/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Menu/FastFlagsViewModel.cs @@ -1,15 +1,31 @@ using System.Windows; +using System.Windows.Controls; using System.Windows.Input; +using Wpf.Ui.Mvvm.Contracts; + using CommunityToolkit.Mvvm.Input; +using Bloxstrap.UI.Elements.Menu.Pages; + namespace Bloxstrap.UI.ViewModels.Menu { public class FastFlagsViewModel : NotifyPropertyChangedViewModel { - public ICommand OpenClientSettingsCommand => new RelayCommand(OpenClientSettings); + private readonly Page _page; + + public FastFlagsViewModel(Page page) + { + _page = page; + } + + private void OpenFastFlagEditor() + { + if (Window.GetWindow(_page) is INavigationWindow window) + window.Navigate(typeof(FastFlagEditorPage)); + } - private void OpenClientSettings() => Utilities.ShellExecute(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); + public ICommand OpenFastFlagEditorCommand => new RelayCommand(OpenFastFlagEditor); public Visibility ShowDebugFlags => App.Settings.Prop.OhHeyYouFoundMe ? Visibility.Visible : Visibility.Collapsed; From 52b6a60d02acf00d3b7d565fec6dc86be083143c Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 18:25:39 +0100 Subject: [PATCH 148/178] Re-add FastFlag struct class forgot keyvaluepairs arent editable :( --- Bloxstrap/Models/FastFlag.cs | 9 +++ .../Menu/Pages/FastFlagEditorPage.xaml | 2 +- .../Menu/Pages/FastFlagEditorPage.xaml.cs | 58 +++++++++++++++---- 3 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 Bloxstrap/Models/FastFlag.cs diff --git a/Bloxstrap/Models/FastFlag.cs b/Bloxstrap/Models/FastFlag.cs new file mode 100644 index 00000000..e2372e1a --- /dev/null +++ b/Bloxstrap/Models/FastFlag.cs @@ -0,0 +1,9 @@ +namespace Bloxstrap.Models +{ + public class FastFlag + { + // public bool Enabled { get; set; } + public string Name { get; set; } = null!; + public string Value { get; set; } = null!; + } +} diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml index 03cb28b0..91606002 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml @@ -75,7 +75,7 @@ - + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index 3d4c3baf..28152154 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -17,7 +17,7 @@ public partial class FastFlagEditorPage // believe me when i say there is absolutely zero point to using mvvm for this // using a datagrid is a codebehind thing only and thats it theres literally no way around it - private readonly ObservableCollection> _fastFlagList = new(); + private readonly ObservableCollection _fastFlagList = new(); private bool _showPresets = false; public FastFlagEditorPage() @@ -31,11 +31,24 @@ private void ReloadList() var presetFlags = FastFlagManager.PresetFlags.Values; - foreach (var entry in App.FastFlags.Prop) + foreach (var pair in App.FastFlags.Prop) { - if (!_showPresets && presetFlags.Contains(entry.Key)) + if (!_showPresets && presetFlags.Contains(pair.Key)) continue; + var entry = new FastFlag + { + // Enabled = true, + Name = pair.Key, + Value = pair.Value + }; + + /* if (entry.Name.StartsWith("Disable")) + { + entry.Enabled = false; + entry.Name = entry.Name[7..]; + } */ + _fastFlagList.Add(entry); } @@ -48,14 +61,30 @@ private void ReloadList() private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { int index = e.Row.GetIndex(); - var entry = _fastFlagList[index]; + FastFlag entry = _fastFlagList[index]; switch (e.Column.Header) { + /* case "Enabled": + bool enabled = (bool)((CheckBox)e.EditingElement).IsChecked!; + + if (enabled) + { + App.FastFlags.SetValue(entry.Name, entry.Value); + App.FastFlags.SetValue($"Disable{entry.Name}", null); + } + else + { + App.FastFlags.SetValue(entry.Name, null); + App.FastFlags.SetValue($"Disable{entry.Name}", entry.Value); + } + + break; */ + case "Name": string newName = ((TextBox)e.EditingElement).Text; - App.FastFlags.SetValue(entry.Key, null); + App.FastFlags.SetValue(entry.Name, null); App.FastFlags.SetValue(newName, entry.Value); break; @@ -63,7 +92,7 @@ private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventA case "Value": string newValue = ((TextBox)e.EditingElement).Text; - App.FastFlags.SetValue(entry.Key, newValue); + App.FastFlags.SetValue(entry.Name, newValue); break; } @@ -83,24 +112,29 @@ private void AddButton_Click(object sender, RoutedEventArgs e) if (dialog.Result != MessageBoxResult.OK) return; - var entry = new KeyValuePair(dialog.FlagNameTextBox.Text, dialog.FlagValueTextBox.Text); + var entry = new FastFlag + { + // Enabled = true, + Name = dialog.FlagNameTextBox.Text, + Value = dialog.FlagValueTextBox.Text + }; _fastFlagList.Add(entry); - App.FastFlags.SetValue(entry.Key, entry.Value); + App.FastFlags.SetValue(entry.Name, entry.Value); } private void DeleteButton_Click(object sender, RoutedEventArgs e) { - var tempList = new List>(); + var tempList = new List(); - foreach (KeyValuePair entry in DataGrid.SelectedItems) + foreach (FastFlag entry in DataGrid.SelectedItems) tempList.Add(entry); - foreach (var entry in tempList) + foreach (FastFlag entry in tempList) { _fastFlagList.Remove(entry); - App.FastFlags.SetValue(entry.Key, null); + App.FastFlags.SetValue(entry.Name, null); } } From b2636211dff17d63cf35e5c5a9745e2ac43cba63 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 18:34:45 +0100 Subject: [PATCH 149/178] Minor visual alterations to flag editor highlight newly added entry, change icon --- Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs | 3 +++ Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index 28152154..4df530e7 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -121,6 +121,9 @@ private void AddButton_Click(object sender, RoutedEventArgs e) _fastFlagList.Add(entry); + DataGrid.SelectedItem = entry; + DataGrid.ScrollIntoView(entry); + App.FastFlags.SetValue(entry.Name, entry.Value); } diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml index e6940efc..4d676ce7 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagsPage.xaml @@ -19,7 +19,7 @@ - + From cf492cb1ad3875ceb96d5fd195d0e1b716180b30 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 19:14:19 +0100 Subject: [PATCH 150/178] FastFlag editor, keep selection with preset toggle --- .../Menu/Pages/FastFlagEditorPage.xaml.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index 4df530e7..f13a1109 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -27,6 +27,8 @@ public FastFlagEditorPage() private void ReloadList() { + var selectedEntry = DataGrid.SelectedItem as FastFlag; + _fastFlagList.Clear(); var presetFlags = FastFlagManager.PresetFlags.Values; @@ -52,7 +54,19 @@ private void ReloadList() _fastFlagList.Add(entry); } - DataGrid.ItemsSource = _fastFlagList; + if (DataGrid.ItemsSource is null) + DataGrid.ItemsSource = _fastFlagList; + + if (selectedEntry is null) + return; + + var newSelectedEntry = _fastFlagList.Where(x => x.Name == selectedEntry.Name).FirstOrDefault(); + + if (newSelectedEntry is null) + return; + + DataGrid.SelectedItem = newSelectedEntry; + DataGrid.ScrollIntoView(newSelectedEntry); } // refresh list on page load to synchronize with preset page From 6d71eb771bd718eeb62b4dcd8bafde87a0350ca2 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Sun, 23 Jul 2023 22:41:25 +0100 Subject: [PATCH 151/178] FastFlag editor - use primary color for highlights --- .../UI/Elements/Menu/Pages/FastFlagEditorPage.xaml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml index 91606002..8bca4610 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml @@ -57,8 +57,16 @@ - + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs index f355295e..112c49ca 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs +++ b/Bloxstrap/UI/Elements/Menu/Pages/FastFlagEditorPage.xaml.cs @@ -126,19 +126,39 @@ private void AddButton_Click(object sender, RoutedEventArgs e) if (dialog.Result != MessageBoxResult.OK) return; - var entry = new FastFlag + string name = dialog.FlagNameTextBox.Text; + + FastFlag? entry; + + if (App.FastFlags.GetValue(name) is null) + { + entry = new FastFlag + { + // Enabled = true, + Name = dialog.FlagNameTextBox.Text, + Value = dialog.FlagValueTextBox.Text + }; + + _fastFlagList.Add(entry); + + App.FastFlags.SetValue(entry.Name, entry.Value); + } + else { - // Enabled = true, - Name = dialog.FlagNameTextBox.Text, - Value = dialog.FlagValueTextBox.Text - }; + Controls.ShowMessageBox("An entry for this FastFlag already exists.", MessageBoxImage.Information); - _fastFlagList.Add(entry); + if (!_showPresets && FastFlagManager.PresetFlags.Values.Contains(dialog.FlagNameTextBox.Text)) + { + _showPresets = true; + TogglePresetsButton.IsChecked = true; + ReloadList(); + } + + entry = _fastFlagList.Where(x => x.Name == name).FirstOrDefault(); + } DataGrid.SelectedItem = entry; DataGrid.ScrollIntoView(entry); - - App.FastFlags.SetValue(entry.Name, entry.Value); } private void DeleteButton_Click(object sender, RoutedEventArgs e) From ce02c0a826d52cc7be7dcae703891f50e9ad0f14 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 18:26:38 +0100 Subject: [PATCH 171/178] Only show log tracer if debug settings are enabled --- Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs | 3 ++- Bloxstrap/Updater.cs | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs b/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs index 44bd1d0a..70fc51d9 100644 --- a/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs +++ b/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs @@ -39,7 +39,8 @@ public MenuContainer(RobloxActivity? activityWatcher, DiscordRichPresence? richP if (_activityWatcher is not null) { - LogTracerMenuItem.Visibility = Visibility.Visible; + if (App.Settings.Prop.OhHeyYouFoundMe) + LogTracerMenuItem.Visibility = Visibility.Visible; _activityWatcher.OnGameJoin += ActivityWatcher_OnGameJoin; _activityWatcher.OnGameLeave += ActivityWatcher_OnGameLeave; diff --git a/Bloxstrap/Updater.cs b/Bloxstrap/Updater.cs index 022394ad..4e091e96 100644 --- a/Bloxstrap/Updater.cs +++ b/Bloxstrap/Updater.cs @@ -75,7 +75,6 @@ public static void CheckInstalledVersion() 30, (_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}") ); - } else if (!App.IsQuiet) { From 2c6d9f2255fb5446cab0f889b1b21d56d82a1149 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 19:21:26 +0100 Subject: [PATCH 172/178] Minor visual alterations to pre-install page --- Bloxstrap/Bloxstrap.csproj | 2 +- Bloxstrap/Resources/Menu/StartMenu.png | Bin 0 -> 256554 bytes .../Resources/Menu/StartMenuLocation.png | Bin 200155 -> 0 bytes .../UI/Elements/Menu/Pages/FastFlagsPage.xaml | 2 +- .../Elements/Menu/Pages/PreInstallPage.xaml | 54 +++++++++++------- 5 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 Bloxstrap/Resources/Menu/StartMenu.png delete mode 100644 Bloxstrap/Resources/Menu/StartMenuLocation.png diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 8b78440c..4248ade5 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -17,7 +17,7 @@ - + diff --git a/Bloxstrap/Resources/Menu/StartMenu.png b/Bloxstrap/Resources/Menu/StartMenu.png new file mode 100644 index 0000000000000000000000000000000000000000..7a54f04df5f861b5b873c6f523d6a68f938f4dd2 GIT binary patch literal 256554 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

q8uqb+%L; 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�GeQgd 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�yerz%BSm=QaG>VRc~|`794kT?t zHdqmq2v;1kV&_i~pht=S`>%faE5pEMaHU{XRZ-arRud?C}boPt_0j9+~-e0lyvC-BaOq5hn_+1OJ70Bb8jR1#$oc$$VN$4I?A%?t>Wh+ zxE50;3Nv$1lp%m3+q@hChy0=v_%dK6VB*goh|9{x;f4hdBXn~OE{)5@Wl{0yCr}j` zABQWWQ}C%6Y3S~}7sZp_MgD|uqjbU<^eb3~PsEkszY{X>|0R{9&#g^}m~ub<^R{JZ zICu)5%q>M^LJlG#v+#-7BE*zW!VNXs5nV76nRz8htOz=J0z6p)MgvQVaqP%p{Q37EV*Tn>W|eftKlRw7 z#{O47`zgNnt#9Hrfu;xc?8Xni^KCPkoi>HJ^6O2u8`i8g=?QN+a_x%*wscz}0A`?y z4IyRVN^Vy3Mqma)Y+$nrFi6gEaGE^q*+C=}=Hk=CM&X*nuOdtSe}zw-#3h*p2pF)6 zmqsYo$S22v#DD>-$95dWf!(LfXJ|NaonXbu-v_n}qzL3VP(^XwD6we;8h&8;Z5-M2 z4xZV58c*K)G7jDU1_q_yX~60;{~9IREAU^v`U^Dm6ZMh(D@C8h>e=_=z}`3U-63^=h+4_ zUQ(D*uwp(0D~eFXN$a|Qp>wR<;yHu^E4{89y5s+X^UoN@Yryj+Sn(Wrt~_Vj@|f}b zpE2)y?%pb$O`4gT#$ztwz&!lEpt0vQrv3lV-g`$`Rb+qPyzd|HT2K1@CIAQA)>FlR-g``zCeIXG)RDXoJ?KTO0I(<%U<3F8xJ;NZ$pFiW6{`%~0CFHi znh<@0FZ_^(JnPnNFfcQD@)TnSTmgIlP4LIqDfr?ZMN|uah-BdpW3cdd<_w=G|Dk*D z$dUK>{>DCv8QMG$8$W&mLmtXNgb9;?7SQtLD@@wBapMi#NMs3r=n4d|VBC~Mq5w>f zJ@%LxypA{OAVjbR4H{(f0kCA86(mtBU$Nv?X#P5UVs%Z(-FPm8#O0`8Zj^c ztS)`@S*m!G!D`uV%D(Xq^PhXGq5^8iU{zj>H>en}%9%#_VQNEhFbFt)rK1$bX67w0_G#fJ-gj)=8XFM z+3#4`87;Z9;RV{tcME;m5P|@B{o`EpK0S z`DJGN=#h8LbPUA|c!jwElLi~okXLly_JI%iLbq1u1 zsXXIK`uk;_sN;2g>7SQZQm=oGp)P+LM%TB)IICaMpUeM73+6B=&E@=$Z3vCA`Xz(a zDhF6$@cK3dR&N zySCimn}({C3b_ITTt%O5!RyX}(BNSk(>GxI>#x5x4Usf(_8%J9FTVK7G@$6>K?Gym zy%WsaSz9)5Gf@XLv?x~^)OBmUhIY*8vDJ<6hsQrQ4XlijfemG$O9|(KzxR%OV8-Sk z54w_27JU2k=|^w9wa4T?`oVFtPrP9!`z$uypwYofUm5wNq1}m{+-9Ray1I`hDg9Z(${@w70bH+L%LHHfov}tD|NH~A|27nZdi^6qV zwroZ9wp?rY;d)~m!Zy<3w|*V}bHhF;ACVyV&6qLEq#?QlJ8ba5AKnJUHlPVh{C0?J z;r@B};YW-g_JL!;{erGT{K1ajYW@0+#ur_I803zD=!>|~-n4168EC#?!v=clsi)W< zW4@@~}9(?dY13s_=ez3l3)hbgq(f~F9AViq(ckI|P^Z6HvI7t^D{z*Yp>Gs=i zXUKb#zWnk_KG#!p%{AAU$QJeqf8>)0mIf$4X|Srz;B_or`@(TU(rt-z$9bU~>~rZ- zFQPa8-f^^j>ox;If4$~f0}B8!2$NpQ+ipn5Gz$Ve_^b`U>dfiW{M)QI*95=A+O=!V z`id1R%na}M-+#ZELks)I-#hQTW6l+}7JOb6{7*LEXwn2kJAb70oF8*bVM1~J0c1Y` zqySd68ob_yfe-)en{vYY!g@UW2H0V&8KQhLNWU7a098<52CH73I(eU@>C%;Yck4lY zx>r)49)K$ktcEaH4QHr=qJh;NxBn|)u(E-wFgwFY(p^F~U@$Ayz?GRS6b))MST$y_ zYC?JGNtBn(H!OqIB@6@q!4*`S2Op#6tKOm3OLtLT#~xI`4>=~+RYSiowYJ1mgYIDnE`p+hRqKlj6QF7B1N^01IE@_lY z|EtlZlySv_lzPolYJBxN%KYal`oo`RQE{)A=wDA9rZ(dbQnO))sb%kdRB*#f)TCJ_ z`fXAvrKA-xT$RzUQf{XXw?9P{H;$r|=GRbhMH_0vKV~`qciy(Nf{%kAqQX3*kB+`) zqE^p8{e%H0GrM^Wn2OY@(9G)(-8aE(V^(y0f(Ch4E=AYO85%okxY?fa;C=jW$Vr+t z{Shjp-`z9YB?3AbaD{E%f@M8)#^! zhv>gCSPkv^AT4=r3%&Z-YMMWHBfT+u1HC!}1KHoC!lo7U>;LCMdiud-raKVRFO;QR z>Vef90ju4i!Rr`f1+d!AaD;JSIKEh56^dGgx&xQY+)wkT@8UAI&{GdD;QPH9Wh4hp zmk+=SzyYvAl*LT9!1p@-a|c*KvA_zApg;~9XFyF=)nHReVvLM5zGwiYYX;l9cI`Gk z_ucn^$%8a>`QUHk#?94vun&PO3_?cZiGj^%fU&=$M~|C4S6+FQ*%$I)iF8Cr5Dme2 z8stYB%Ei8Lp3+e7-o4k9f&IvSQ8v=!1uN-#w5MB;ET6Bh@6T*(; zojP^8@qO~ir;QC|AUXwb0B|5ugvb*h0$_o+{P1_*efRM`^SN9PKma{x@Bu{=Cr&i^ z0U9U+Aci;p;0K%dBMoH(Okl_QGtWF@%AYi8k^u#QF{BBo*|6gh{OdB^f}9s5Hi0Tg zjt6$E%e5Fh*n5WYCLiGG@S%52ess;4H{5I!v+tj1}hoBj=}3ayLC5U)rl`Mx&Z-Jx8Hh84Y0x(D?pKel>n3tRsv79 zT`NC3jdF8X3{C}EnXC-T%SmM=ahXl1D61(Iu}?ljRc3Z7HOULmFZn;bwiBmQ@oO9D ziZ$<0LFGX6xfFCmwdIDrd07q>6=zU+h1XXLsPe{H@qawU`P2e4uNUVsXz>kN)|%2Q zZlabq+(RAim_+|8nH&C;RBGJ#50ug55^CHqmHwE~o*K69Lut3XK)?8}=jitxU!lLh z_$A%^`d8F`HdltzzN6exA5e#ZnL?QXb|ZYTk-U3rhG{@J&Ci_!v|GM4da{<^c}F&+^3!49vg|m;o#yf_3dxSI~7= z|JlF~wgs#vjl0MA zh_}Gb(ArhYjlVz`(xGPja8(pCRG~`<{~?s}!-2Oi*{7J#wXC?6caHqU`iGx((jY;x-gJbAo={kLCGoD&2VeA_$yT(YjcH^?Ds$@nf?1-fYgZ zd7#M|G*{{NLwDWwo=a6#w}H`Lcv&NJ33zND@^^B^x1H& zW!Lw5e#2?B%Y3i{968yR(pJO0{JO{w3X`PygHXWJ7sC(eI}UoZ%6Os_Sxrfy0(Y1k zvw<1{V5k&eJDSa1@|WkqtIIze(Dv>wyMeY*x`9Z$KAfs=DwF*RbLnad3FZZvW6!xD zA~~@p{Gf?F6CkWwC9d$KU;2r4TJ^4@azu2kF`ns^VrULaP+4Uk_n<)lUdzyTVzqM1 zc<|cpkI?aw?qmV3+P^+uJCL<9AsTaD9Nd&!{h#`S4d?nl_4uX#;0%X`7KHqhCqTY_ z8_oDn{R#><=Z0^i42Yo98a+?$+AIj|{KuY4$eorOlMtaUJEyHk z^D;anoe*mLM%Ow?A6YCylTC;3kwswMJb;)-i(~E+If zM|be#xL-ES{Y3D4;!%Y{3Rq1U&-E~vgFlHGpOl$|kv(5dEKH&3?fdu2f`RfU8X*-4 zmnkJ9S$ib}enk9*PEmq+Q&I54T}lBMrAev%{4_>B1RESJK#3G1r~)?3g!=QsIL$IL zn~JB4cPcJ^L>sg%?iJaTG#4gJvS4z9klz|@C9i+>u>aFp{xt10L-o7k_94zUb*)B6XE6d@ z=bFokrtfOZ4HOi)v!e_7s>8#GmO|Vtj#R#4B^#@{!U{g#>ng8Pyp8mCUwQ!`EA(6W zvjp+QCVQOO_Mf=r$!6E$N$%+so@yUpi?pz?AD&u_qrbeLj!zF!OFFLSxpzq^2J4o0 z-ey{d+&s%YTDfj?=#wPOb=2Ea)G0aMdXS^%8-HEuaOs`5|FrC4xNsa3P{)nspKs7! zd_-8GO-LD~xM}=8q?mT&mO0@O*0~=FgiJAceHd@Cx6sT#;Qkcs^T4XpnaQ3iAHlTd z9aVxC8bKMC0js~C++m$|lO79wE+P^fOfeSf3y&CaHgM`%>?f zsD1RGXt;MeeplsSVy*vVcH{l_-)C%&-RvF><5}fhPZA37?53}`Gq!h}`a5)|>ewu` zFQ8(jfghWvvraD zQh?PLQvd^fyb!~L`TdvF9g@FvSm*rMiKj*c;g3=znaf5;cX+Tp|K-TmEXLq^+GCBM zun27oMo;lcJ39`J3w)SRc|~n)7XwZDglAZRK#NqP#W!hiH??hh9%YI3XNgkCzXVHE z4ml%jT?X7F55gJhIPKB8Zd1k%;KtR6&p>DnE?(N?c8_j}e#hBAcyrK6V!SokBT>|S zGh$OKF>ty~h*T3`9PSU+IJfv1RI|l(OXS<~OP&A7LfExhq*9GPRWKjZ-Q|iK3 z5`eo0YSWroMI(u(v1V^B$EY2y(1~`vEmGR0D@k0JWa0B# z$SO3O&EPc7gXT`I!@ijE)dPjg6RB^rH2PhT>$YW`Yn-p_Z)*JS<)nYF_MdjNNoq@Q z12G3>HYv4Bl?@hrfA{8N#BKnRNEz4vl3oC@;;|gyxz}eE7zkXo+L9KY=ob$$VXaWT zzm!R0A_yrXmtw(~wenaf$@UtXNWyX)8TnJS%cc?ctv<`CeCS$ImaARR$rAmp9U8bH z^RL&Y_QPm==0;6p{E=lRUVgfr*v3`cXb5IBqU`%@75X6f0kvMAe>5gN-2`oUL@m_j z-V#=Q>$;G5lZ{qql5>7ssWbKLneUUg+BohH=$n@Zk~p6k@88WE0!v2=3cs)VU;7?6 z{+(``ikKGPuRDp+8s3&;dNJvd%Rd#$yFMv4>0Y9^B$2hSB$?Kb_XA%znVaiFJk=n7 z10Rtrcwf0ff{`hcMGABy{MtEU_phyHnqW1^fPc(Z5#^!c;>2&x)?YT-U*}D?y=EeR zQ9`Hi>|@Y{!P5sCZ}+=WfKdI4J2xHT?p0`iB#yXqwfx~ZAOcpbSL(azc3XV*qmMUY za}1{rM-6{g`&cBr3Fcvs|Ral*`I(Bgp*Wj)=MV`_;%I=WWdOH&0O1st~0Kv)$jx zwZFbvF*he&th^HkUkshdBBsL!nsWD=)qMQNU8dxwc2f3`whiOo(1(k6P6-%Xzeo|E z&nv?{VvYbd`pDW3at9ahJddshX zY&tYqX{?kQeP=wU;PX%8*J9Ci0c9!@D{~stFad>dmDrZ~VZZ|7MO!CMQiRmT|HQEz zH)5R!ntq&Hm-|n1l};ob*#p)~eLnm3ajJP|B2l&8~fYv)P^2o^oR&`f-kYXUGTTj73Cxr@2IO7Nyf(-c$ycCwvQ5pK!U{@%`!;iWc?VTpZ| z$Hp}}kJc5r`1$kFFCe0}oxw-!F!T|ni3l-9v+gC9RegPyvRJXiN)u{$yq#WFIem~$ zi97#kr1|r2LSD%@*CfT(t&UL1?fk|*I_Q!{v(1ak!|`T5sJX+sB#l;qv9;(v%K0kB1Gti8{Gwv8o{tu}3RH-=P9_7!$>gg3PZ=E)Jfd zZ|?WfgQwHwDWyL)9ec}lNZLz@g#P3f2}x9X`Nbi+2HJS;1!;(xow&+bbh>!^nx$e! z;>9ZX%L6B1mSX6P!|9Up*X8EK%tv1ePX)4MTvFurD2`oo9AU{&nm$C-7R!qjO+2|& z&wdG0Ii~n!xoBBBrU|{k>`^IUAve;Ju1p($GoBRfSMqC2 z)@WvqdN}pEI2aw~r`WW)m2>%4g7me!OKaS}>v_;x;>;Lflv&@K?$HW5?Z0}7R<9Tu`GzkcT5|gHs?qVSyk53*EB0p zgKRSrX#$fx=p=zMRgHQouJhtx*Its#J~~;_^*St1qBhxX}3X5(OlcJ?G(SvK^3JpGT8x8 zK=k!<#dMNI0s0%PouEC%C}|51b>_sHTFS$U9=ave*3Vvmf0zIe{&+^>nywI|(sl}A z^m1(x1)0+9*1mCGwG{W{*lCG|YM*iS!thmGVmhYC+1lyjy|&8N#7JZqLR2W&b?FleQFetn&>Sl_CblkSl{HcStbedXM6| z<9UQY7;!NZp{xSU*2-AR(!(IbVd^q{^^nw%sM{^|@4BJSTEZ5@tTZm(z8v>3x755C zGe4#V39P7B{1;Oca(fs#y{64>`+ZSqg z7E=b177*TGh5`%}S|=~#O*vyb8lY?Pzp{a4rrS(nMf}kd{=mQSf^H{rL+?Zp}Z zU*y3EfV67@2*D&5NomVcV?MEOejP_1qll<6-7Pt-_SZYsr{4;nB-i{EFEB_QPiakJ zmNVbaf&pz`0ba^|P_j~=3YYhoWSg3mGy|IXPc_VwP@3hCDOGoq2=+F3~CIPnt+$@E3(9+Z#dOdy)@zmcEQP=A3;@&a!Y^e|zb;?AzpZ zLoC&lTRXV!v%K2iKdD81STC+u6a1XICc7W*nty7az^&8KG{< zYH|MfS2Dz^7s`u`^t)gmp5%j99rtpr-{n{o;L>vaFd9KZmA5B8pMt&@a-j4}>;ece z(`dCWf&TjMA^z<(!umxbT*I$+g6N?4TnK#+K)m`6XbO1h3O?{;KNwK(#27$k+_vAe zL^iC%_~7Mj*#=N{OoKhG-6Wg$W;F;HIycA8<6b|F`@=nSvlRB^+CWk-&I1+BR_nQY z!vpf&Oc&ap6AEmB{0M4X7;PnJ#gP;wZ7bLb(l^VJT%lf3Ql$_l@V9yp6sdi&YYBzX z6DEOSm1l!s0>dVU0D5D2xF*v`wzD&VdSGPw<5WB?;fgn*Xfn6o_guyF?6&Y0l!x6e;NG^QsKm`c!V%&F^mMntx#lB_u+TVLVF5V&c~Idw9ruKl$srXpwCuCMiok z8_h0{AbDaToc>V3fZoW1O}#_K^6{wdJi+pF4+vBAQ`g6W0f32O+CC- zj%iAL#LxH*h_jVnao;gU3A%zY0KKCz#Iu+s)h1?hLeby{3JKd=As*vNQzQR0S@Oiz z$ov}*BrC$)iL6lx)Dz9bf*ZNdhk{%}Pyl25irsT1e2dJnH-O7RD;hxQ{PowZkb!w~ zk+$|u>zZqLC;wTt?6e=`CmS=l=IKR#LZT9l%(Sc z_{0bD&ePHgRXYOIttZ_u7!%EGkBsYQg-QlvKg+V()ECh*a;fT!S13xZ>k}j;>XBks zC97He92Zz!!L#%Fl(=F__%rX`OojxMN6T8mZ`Uo?B)BM{PL za{vZzd>Vpo1v1Wy;$Gp^DoIeh!cr9?as=2A(R{(gqN!95PKjG4?MYimvj-K@%KiZ0 zXfg|FTVY0S@<|VHaW(ZpN!zWonNl|*IcK3rq*+YzCF7~cW|-Z_vzHVDamVy}n0#&{ ze3e|aMtNI>%RsX483#w@F$bmTE59lN{zyzth}Zy_#+m>zyWKlMi5XmGL!&#NfI?|( zm_lt28;n7F8h$a#DT%p()h8lP8`|o1``0+Md`7q9Y3Yu?!AM44Wy$_y^2XNi_*Nbd z<1ZQhPpH6zi7aZ1N_G9~?U2!dip>{*J}aoYX9jKH`3PonMkCYlTM)Na^-|#aw;3i1#3H;gwSi_E89MaahxTilQp>-j*R>bS&XeAt^=o@s`x|>I*wTS;#_hGf z^Wp64%EG^Y(9Z%`V4ra5M;476Zndt%7aJm^1{Pp5;^}C3wqz%Z1V81m5)eJ!M`A{Y zPZxlp$Yq6T2`A`=UstsA4JisZz0!WsPpy=xn#oIO%2Z1LPq94D`NkvNN?^ym)Z>%f z{Q7XT*f?=$iQU2d!Ya!30uPi6ryGsREg+PiiOkqFF->_qvrx=(6z0ohtRTQaMlQ{Yf0K;!2u#H z`nrrn^Q-Q6B$CYY^dGurw`~eA)9z&9IJEno(%gg12G7uM%HzBaeeo&`mP~>CL=a|y zAN{u`G3;!n9fp1$!bvXpDB^ZxeN*^>+#<>tqR5n!!|ajj!a8kIvtZyd8Z?^mOc)!U zN`eSeXM_r|zLp*~%Ti|=2ee7=p=g}4i3JX75Q+2MMEL^LNeZk%+db(=XzXsj&ArE4kIiM^^55O44g`(vqL-MBag|W`@h7$pltx08FDJ;9G?I}`ux>O5@ zzLdDGDOuN3tnqN9!Q*_%P=V`=tXL4UEtwgp9Z8m|i8-hSqA3xJaj*bP&56C%tn$P`-K&3@uov8+b( zy}rO)cZA8;wg-8!Fg!VJb=&^)x!YFzt<10d{)zPd#jJ7HFM#JyWzIQ;Y+94d+bv78Rb)5WKB_&Dkok4&YW3yz&Eb7l`*UHan5{=dz46w_mtVsWyAo!F)dcBts~H>& z=53Eeki)1I**VO;i3evZ!aekkpK#Z{SU3zdA7eqA`$Ub0XE`VaQ|kGIFpqaQBN#KR zc!Wy4hn>Eqi+28Fbv`>8nRcHyac&Nfvro!Zza65sddkTk`FBHtB0JWYv}&{$j2-@Y z84iy}-@!HfG!J?+;|;z8pz|db&F23>#DE3OIaVk$IK@1(5r0z-gdbaVI<+}AJ}eKDk=ua-{kL0ze=lXVOd(=VC)!{g2uTg-f1r&S6Eh=H-qC_eHv3N5#RuB49nDOz!z;z>BupW(KGwsZLJAyK@kevNk~r4--RW>>AFLTGBR^3Ik;bj5Gr|H(#0{P(U@RkwXt` z1{x<-wYAbH1!xZv_5<%6VY%ir9bvdrfK6p(bloG( zi<_Um?pXk1X2U2^L}K0WR|*4XO*+MhE9z2W6UhR?t#=~|k{y2^C#uv+NaZ!dov{%l z&e>jWY({@~ogmfJTg&euM-8E`JXV5IzPvJ=eegiS%&+(h#{_KdZFki@WB+}%H?Pmi ztAK!NTWQxpPiv~u?k(0AEx(iYiT$^S#r>I<{09C|nlw+jG28X^1aN6jI(6<0K#|t! zk}A|Fp{P}|R3ZW?y+gB`I(JQk9UegVnJ_mgle=v`-|*YLm#{i~{>vhq1^p~lqswU` znfzs^rby;~akXhpd3f3f!5nz+WHIA(Ss~x2b$c?!l2Uu-3XVd?(i|iG^uEHrNUOoy zdRTE+8*DwRx%}M`T(Ip*h#Y+zx4LUEEb<4B^c7ssuO1qOw=uSjigJySch*pK-Blq^Lh45;SES+)F2h&vmvk?h<4^Nq}r?#P2l2> zW)peuKyeUvsF%O8uf(7LoNkZh5h=;cPKd9wgV!=x_>@kUVNt~Ytse_*HVjK7C!Hn9 z&5jEkd~&m%e&^i+x?QsWBWSm#hkO3ZLCEHW|5M&y$o22ZP(8`Z%@=Z|+!5ZXp*F!> zH1rWa$1>U5n?|W=6x!d9!Hh%HsWKe0#>e+QIIh0)YkcuVH1}n()+LKMGaB%aQVnp= z<340dM5^$iq-NwpO4Xtv`9}h8W0?St8xuZB@nSwgxBE#J^P%fS52z#N$54T9XCvDA zcxr-oIdabqOw7X{Gw!=gjCO3yF^vY~Z74Rq@2AQi-L!eUJw&Phy``M@1Bi;XMVYB^ z)Gi}G|A~{6Ww$u8$g4*q=dd(XS{1jN7EQglUetW)dzX6K?O9#T?$PhIU=(PLL;^$) zvY#tI2XTudIXokM@eGAzG{k086GEhmG&8h(AR=4KOne5qW+cn*tGLspC~qTq5+a=NA`&_5qT|z4hY$T9LY2 zD@m#d_L0L{oPbfz!aa9;S_yQ#K)pi=Uhq8Um3F4XytSQ zB8EDeuX+}(O}SRcZi5d$ZHD%Lg8JwItHhhgdla{oC_|C4AcPu|jbZIQpc>#2qBQ#H zoIS^^!5T;Nt0gsW1!z^!Ur8=YPG-89L%}@G_iaWI-oIs>o3cSkb+@PA(^H%cyoXYLkmz*{Er6$=a=_!l8At1G3O`92NTtRz?|5%U3u z;g46jq$14GB$dWaJhqeLGks&sqRf=cL4^*K@K}co4bs##wT_3(K-B~4A&@rnfAwLT z_Y8GBHHk0}1t?f$;9u-RMc;m<_6dmsQcMVHJD895$RCHQ?UGc0c#B`t`Mg~H^`+*b z>vN{%v!5c}?~t^7%^he~V-tfN;^Ru+KIeZU3vTFdZlu>mSQ+~b$b~h?h%X8+^uC*1 zJfqjM4`g=uC~FL9mEBv|ho5*j7jB*1iLwrQAtRET)cu3fm{K5C)>i#Aic&I`l`z6a z04c0c*3&|C7=J0FKu;KF0Wr6xr2w@aA2O=pQN{CdyE%*DT*bf#B6eFAkwe-nqt^ND zIWwIHz_FKrVCN%A=k5c7rdqPssP;mP3lQZ_3t;HaM9%n;E;7F+9t`K00Qk-pju1i7 z(((RwCx&4#Zl$_eCh4t)we!DTib1zYdP__pWy0T`<-6{bho2; z_u{@k9lBbpBc!rs^OH#8Av3sY`}q6VXifmCRQh0UM(n7V`}u+NhXkkKsaaiPSV zP1PN}#lY)72QbR=U%@3VI&0T+>+wwp(%vym81S6T#rr@xpd-c&z*Y?EolXJFHn zS)Aa$Iqby?NzD?80SeG9I__+SXzxzEfB4hf@LmD`h*E9qYt^>F^Jk*ZBKL^)*UO) ztHX_qepaC7Qpk@YrQs)wI&C-|2SM15!yND_EXQj#3GG{G0R}Z?hH8@|NFiI!k^Y8t zbXD`SOJ>Y+k(%MzWW%$|v25XB>7Z@;*IO4cv*U278N;kRh@rV5^*ewTN(jKPTtP_2 zkmHUb957x_;!xk1IZwVcA*WQV8>?~hm=fb7U;&?Ur288|Pt>1hXz0`#(MAIN*r7b_-RRmPI z1ct1u4|8SrtT5zQ8?M^<{$bh)m;smsd=XD!=YP_tsJOk=U^k5?W|VET?PJu0y%wd%_=va2h5#E2FhI z%~soDm=}pFdZy{NKz*&NteRORJNJ+~98jsZirrzrXgZ6=pkkC)RNPZ>3XPds1Wejiz2<-&g+2rf~hvshzwQCZ!qS!5ZW~Rt;36b_&u6J ze&Vt1^sbwPc+Sw|+?qvYSYDI<;ndeDK2vM0s4E+_w#+TMp|TT);0QVDqa+K}nu!c! zwAP=5;|eQ<1g`X^D{x^Rg}wkDrtkw~gI5t8LBT%DMXF-O87h~jtDaJ-$;R>9sSDOvk4O*Rpz#he&@wjs(O&m`O8oOp7G> ziehFW1No5(IwM`PZ{8AEnqgSJb2)i6AU7F4AYR9S`*}M4Fj`PJYjjy7;bm0k-9b8l zg%E`eq8h35}-4dp+Xr=b`T+9l&!9WyJ-AeyQ*2Jc?C2Spje6*U|SSm z@+?hJ`Lf9Or~Hjun}}7kR_#Oc+K0Ak>RF@LbfEZudTzt?SlamkCPB7zIudvt|V#MPhV}xTPmR>R~~S!>*kfLC@2~VON9w{GXUAMx6R>Vw7?(RdzbWMg`%v4kCZt zt7^68w|^0V*8Tv zuaV<_-?zTJPx@IiD1ztBrJiw}CZx*!8=+cKM8NJCzcMIKW{zBr!y$|HAaL#G@n$)0 z=faCdXknF2L8t4E-3mD}sunN$uFGfOfm!oZ*G-^`HWqZ?I9I=_F|%_=&~&)k`YZ5y zb4soIx%0o22irI~6T{^rKch}twsqYcB^{5JD9L!{hw;ai=%T8UXH*f7QRW$I`YuhM zgw$WLEGHlLKO(%|CTavj+_%ioVA7qfe?0;GzVy#W(HET7#F^HnMI_HQHI5t#3v!Rg z$bm<$#s^~@I@tn^4Ac?|pL#P$mw!sxRgr74NNSn&IatC7@Pv0MWo{HqjncS}!O>cq z7`A*yWw9oKZo(8=La@j@s_6r<+rrUH2mNFF2Ni#FuYLR2ECjZ>mbQx98PQ*0q{~+$ zT3SWVqbnay!AM&)?Xkmp$PBj?p}{UM6j!l!G`-1HO>9ZB$i6`wMJteZhv# zqP>IP0LlB!M~D1LY$xI{d+G8~f`7WaFb^NWhoVD~rNL2XfQfX`q0(98)jg44CgTF1 z>Fd+~E@*;N0IBdA1-|tW+#K*eGf~Q(Votmg_-!;i&eGPRbAzhzCW_ zi{#_x+ost?30-h<6LG~Etks52{Zjdib1*d5jHJ&>qKRGI(c4MQRMh$o~WIQQOBLy)MqB%Jfxo&&W!~`%8gY!0J7#Hp4ni56 zE$qJ^WHQR!)!vBvI@P!WDKVBYI7ZMUH>+!BlJwP2q5MxK|wlp{M zE>cWyBFuFH^F`krTUD6_ri$h@M|l6!DW)J_Ffdoo&&d;{S@|K;A=pcNo1de@LV&L; zg;B=-q_q#R!|Si9t->#qnu@B0qqW$lj!pyV8zB*aJ~UcKTti^9GDLlf{+*>8GGF~!9WKO66z?$W&mrJ+m`4O`pPmdy9ohQTQsD1+z7D9IP& zI8xb*$fqvt!zt>ytAyY~v!6g%KA{1*S_8o!f zNFJ<}+IbRZBP*Lg@YN1Vk8!A*v9MwTdv(vG=?la)aD*(m)zM zEaAOY%|TcICYH2^A5hvoY!YD`YxWmI01A|hJK#>9KbEDjuf%>Ek|BOOgks3pD!^%eAsPpOkv+l`vMnnlk=cQ~3P>iNUX8Mx#M$gKEYrETcF>j(`?hG#I7K z1N(Sz%H2;FSkMW?2VmF9rlbQr&VjYV!{UJ)3adv`sElX=d!`m{+~e5?)0Ki$I8Yj7 zn|Hs4r;Z4VilfM~UG)>c-mbCExkiz4Mr4v$TJyrYQg7`XjWwD4995WZs_%XZa-g-s z9RWT)3yHjGIN+#a{zrOURl!lZnU$l-p9Be$cHNn5Q!yE(7GSVf>rP#`BDNvh@~y6!c0K3f17zcd7nn~U0YOsL1!eypTn+D zC?Vz1J$e{W$h7V?HAtApAZifSZ#mRb<*2N1zN+ZtYYM;uOqnecw!VEmG(lb?R7y&; z1x-(*wrIltzVs9xqCOB3Wtl88O%;I#KB!B|_21)_+G}uy- z3Og%}sw=$aD-s8XfHZjGP+ySxeH`7#bNRKVkM9bMZ=e>RT)Qv(6>YNPi3TXneX6_1 z6*?;8d7M29@})~`JXr4+azXcgWc`z}{QH|WUZKcEjL2l`_fC`?$?MbS1q#xsMdbQ$ z(ui3?je1Ua?-x2@6~M=?ei^%WpDPkrStllgCn4l85<@|eY_+Zx64}yOZs(2wurX#{ zC98H>!?YcnYfhb`$`aa|&q~mkwPwVdHsBt_os@fhjuQn0`UPI6o)V zBB*O0Ms+4I0d4-)kw>$o&E-m+1XjV#>J=4z^T!{NdiE+{#eyYC=u_hX&$6Ea2{OW! z5HeUshW=Ywf?rb6MlTudg77 zyjooSu)t}gWNlhVfjP*0%vkn(<+4t^AS|9Mza4<*&GVLGR$zr0)LF!g8@{zEpLM7! zBlcmg^`Bx&(vEJFbPd-4kTpEKVS&onWnboIE_5rc=!3e#5V-A$eb9T0TG^`DSQD&&!yIWurQzs7H8(v ziyF+(9suBb>$iPgS+S)RJd*IbVa29rhlF6g!Mg1Y$1aa28?JY+enzyG0*te%loWCk z18V>(TRmV(GCjfySTfZ(>BymTAvdrY&t&+J9MF`mHT|N>QvAbuxPao5{C|WERR*aY zNz`yVb{OtjT#rMaAhVAaz>Lt*3ddQJAuh-|2g~1-YBzFZ`x?f1eux`==%PV5KsaLldeQwQ~^xR501DYLZfz35++-8 zCj?eTd1+t$RUuP7E{PaB{B?+QOkzFy{etFjRYr@K=ofd*)@>$3cayvB=t;pOk7)|6 zT*J4bZz|S?Oe=%Oo(hHd$bB+zdY`NKF?BL}S*5G>bl=x2VFvx<-R-Zn;Sw2@a2DOq z(6>3&aURN2u^oV4)#K0&H8097gaa!?7uH8Al&Dq4>2Ve1 zE(}HoCtK$bTw3R5eop#SrlP^MBFrVZFhgv6EC^Q0u*TLj1k2Ljh_y93n3kG$?{jc& z^S_r-XRSf}^`T1TQrqPIu%@6$>PQBOoG&GwiCV#m3B(6Y>|d>&7f~ z6E=3mx%B&eNfTZcxumX=)4zTiI^uZfo0#yEulT7%;IoR1wI2F3xyidp_w^#- zv!Y}Hg$dnTs7c(gvBMR4L{c;#^kIEuYe~r^RS$0N3dc}7@|9kNBx0J3zYAiZu4{+qOs<1Y z%YYr1lib>$P#(mfs+AufVu01|?WwV1MCxZsP)>LG7|5?q$YalH9kI z0*Y_Rr6vVsL=tZF7Q$}`e4^fQxy=U?c$0n`l%#TfcxgIlC4soO`W z0-eSL=h{p4-4jgI8>(B4D=voO;82X?Q>LR& zxRv6NQ%ddBlgI%mFmw+-dN4s7z2bmU;L;U2Yh7f#p2CrQ7A5 zR+d~_COxYY%u26ou8hLjigXObZ=Hh^* zykOsyN$cFNo=rc8z|tQ5vO!+Mthu-6LFNZ*dD32ky}oJ*)fb#1Wr<~5J)Z+muJl%# zDootqm;R*rL}k)uwsDP)dVK!EKxC}BZCv}-QzGOim)DhXRS4$L$bK$lu`OS2V+uvp zi$|PKLPW9(M8X6CiIm&}bmHKEZr3#ccbs-BVmK436%t;DhTHchUlUA@KB)VE4E8+B zm)k-_Q>t(R`xpy=2C&to8kG`&*$2%{3B z^!8)#_tn}N+=gj`5=D9JzbeEh?jbdaT9l{Bk9C|py~8pn-udRjJEEB@XzIg>YS*SD zV+oNpsgH5w#EsG`pYO88|4gH(_00`dWl0SmWB@=W1n~*lAGi^GRaWvy}Qbk3(|1Y{}llPGZkBI zktZ@?Tw|+}Eb(jUzGCVEQgPl>Vns;xyTjct-hMY@dhzm5!h1c7qoiLx>SVD!((vw*QC_?Vul*5n7rlkdGw%{}4L4&9oL2np={bMoUh_|f&5 zR^101%hOl?>@RPNZ9cUnhb-;YsdqWwnl{znN6a3{`i^}qaoL^?X7Ad=4{Y9LuPX?d zUv>VsUT~w`bv^}aZ%+^L67+=?oXMPUWm#$5{?eVD61!cF3z@A~w30;Lv40vAK3wqZ zDMx09+8>ks4@c`B`qh6)wsN5{TMMltg4K4g>y(X}Ehau7u0l8}cSEMcGI|*l0-&){ zjws0a6=wY3b7I6#-)LU#>J>82sAhsG-z>-u)8iTSRlOwWVnQc-_{?6N%6Kiq(4XG@ zgmrz&xTdx|tz)nJWtnhE)=Ny;g^%o1@x7+0_W8W+zbtIqNjZ6r3b-AIT|y52UR))y z)G4d&o8^Hs;{}Jf0WrV$0H*|jcVt9j` zm5Xw0<28Mn5P)Fz7cDJ2{)7~#%cet4BG>ORd6FTYpeba7K_p9djwQ77N*_}Cxe5Zq z0Qc%6ABytm6pram9H|5;if%Woq|_Vz$Am{ixGs|vO-r5>YOV-yl4)P8_pJoXtsP4P z1ljK0qhm7__5=84yWKp#?mRwb3bw2|bsE|6qgl?3aD7l*n(Ed}j6Ga|blP6b zy9l+5y$+r0e~~X5mBMD2(I^T2M!T&%+b*{!@z$W#x|`cCOZ;1S`Qy}v^+-WJU*g{t zuo>IlMfWXEqIN(rz;Nr1DlY}daR~4yp!7I?;kjoBrBkR#iJxPN)8hqIQt_zAFaX5_ zJh)gLcj_uWxi~>&^Jm{pD&SD2U*`BN0v@>&uY0 zH@Zqen)w$7QkdX@+TQ3TDtyCS7$l+ncX#G(QI(vEG1u?ekJQlJrIh2qh*_x7-vh!` z!;{-#h%kWrihO4BMe!L4N?*TwZW0GRO8o-G&ImWT!6poE3mfEe?-`-m}<-Esqy>Ws_E-EA29`^!64kd zouBo&>xp4B=MD6*M)>Mgv{E#)OJ5g!152Lm#3&w~hT1i1wzkkxqxPzinz4)8MNq3oRZ48J_xJVwe9!my$M2l{ z#W_jNece2t_df39@wh2Z1cpTN^AO@rUOjGY*q^qArT`c;>fd?ovxRfZoHxSz6gd}3u=1zSGAUG zG|Zv*5m5$_G2urJQ9?YI9e;?EN*Y9CjK}GGhLdG;C4B0kM~4uUf<}m#XUhAbExPKt zqd%jVtDq7hRBEL=`DgL|tdG@nv4{qH)HD%H;vcmG^%s<$s7lv~CYs%ib)P1#qD=y|EMsIC6>_N{TXQLA z$LsnazzeOA69mwtLKhlKl|f{m41OUN%7Q74f&z}5Y$Hn-E?q*Nl2n|%W)4p$5mfjw z;E5sahz~)5Invz{wM{D})RZZ0sCbO@MRxcSJA1q1gs!O{F)j^3{Agr<0F=MRR}N|L zj|Oiah!if?pV1XwePgkf@sXL|#rk91_HMg2xr)}oTGQ?980bY7wbaUeO!{XVN?&f- z4A?gJj%NmxgqZaSSbmGro^JQ8Yp~w^x4mEVWI=YNeh24WVE2^b>x@Q3In~}N+do`$ zOHednLB4NxWVLzZ^Ybyn)7Fta*Ve+a*3&U;prTz1kh0C>ZBBv(9Wc$xl`? zvP@)Y-3)A7xX3XlS2A_^J^h@Nk^}dQB=6+dKKeUZ+FtdFBqM{E+X|s;S^3U8?~uD( zMmACc>4NMAC+?h3!1plP3rEH{VVv@So7D5}Gvi==5mMhpKc*l%W{u zvV$&v@x{cm)O2HIzkW&tKWPQrmNexgFgg60f|B&e&5deOp!#{1IG``^Wr*i$M5y^Q zImjvSn)FoprwqLYI7fpy=Y>Gdi~H=aWh?|r13imglCljAuMSMUUvYVv?4EW13C8q* z_7j%e;w;;igU_o&hKPt3HX5?TxAM9l$D+rqt16--45djsYm|o0j20+s2fDLQANok0 zW(m4IWILI5vD_VV>cf0aXjQV3OZe*Svd2#dE`5KX@W9Aq>Jpz^E`QSnBb45)f$1!i zuW8O^7hd_cA6va;JWaL{BKEckA@Jmj2owS$G5wgSHCIPOme>)N!(;iE&w|aWGLRZe za`KxIM7NFiaXSIu1au@YzF$#KZjvadi_ci**{d_FRBnAWx3OVS(G6d__wTtijW zVC{W1;UT>fj`NJFXR3SJG^ttdP&z-51@PP0ekr;(e6Cw|cWt((sjWJO~`n zqKHJ?1dTIQoXB=Uks(H$N{(tFHkI&}k~?`OlsXrgq{ANtZz523xj?*>{`b)>X6)L)`!a|xh&3-4LR|% zxA6|tJ=$;jM{Lt^gw7h5m*^3#_&KLHS_3tM-?m~NJbv#qZ+pnwbPab2e)3Ke)A<+G zHnnwW#{!g(8&AiuBPlt{#N{w7q+OFahylh4@fniJPWyi7akX%d%#4X+1+E82>5#F$~H!w#e+#4u%< zO&$RT=xM3?!Ut2=G}Zzyk0BisprQN5PZ}1-FWEpN>linDlI`VjLuZ^3&4?j{2bzGf zr7k|?ypkb>>32qZnv`8l;ZNeUwefj*TxUVS#FuT=iNO|d)ponffs#hc_GgQ>45(30 zSi6Wop{;VyszJL5f4R*y?+zV#F=~I$bXPp}F}<+f!Qc~-hQwpLdcl*=8DmvU8Nt?u z%I*9QiWeDD$Jhz6coHyHhn&1r%T5t+buvu(Eu?K9qW81q9my$wszr$6rekC&&%kP? zV$L71_1guO;G6ya*1rFS6@$gZ?hE9w%z#iiMT&B8+($QhtqRt-iZ|2KjIJ- zCkhTQll7;SEd7 zazg`ednyXmzfnZvEjvLX6iln66kWYlze%t!)S$b-P4iX--9rnn^7~jVrbHpf%I$D8^=&EAES;qIK%A^>x zBJv%nIjHpQ2=PRfhSK_6E0xMqPjGqLL^Ca*1~*3-th4!tQ!i3pOeuNh&3Ux(-!Q+h zeH;?WLQ@jm@P#DuD+x3{fgqVOl1a`~5u1W7;gU`fIMEOoa{ErDqB8KTdZ6EZDDF9( zfUaI1t;ZU9V-2L}7588@eV?8LQCiAmVystk$wNsVMH|%yf~34(?~d~4q(^VSEw17f zOyZg+B_W<+&R)1NtfF6Fe4@T&_~GflNCM*%jv4ig>EHGpORq_~i8A#3;L0oekhBq$ z4x5F98hmeMZwjn9i&J$vL03^i4N^k>` zO%(gRt6|UyRqU~qu>8_ZwZZT~Du&fVx;%qKO7jSaq^Qax#^{mW40`CBoTv21 zBDJZL_%3hp-rLv2ivPj_!D3gQDLbF;1s7Ex419RU`BVcZ3<*m+(IOR%3zL$N8a+6DB<#K@ci;LSUhCQaLuOd>x$y*LgmVHi}Eu?Gp9zkVC=E{ zJMWq=flnD?asZNV>hz}91?frGMNmSKMD zfiQ21IfKryyP+T#9+k-wyDsO6T^cE`6HR70Uq&+sqwb~uVX-3WvV=;-tg14ol-J}$a2Mr%WbxaIulvUMtt+yKNcV@J)1todVMSHKwgUbzT}2?$Gy5G z>)%7k@R0zez+0;Q-tEI|<&V3Tb9sE0_jAJGcwTp9JEolmwvYx^MEoALza=K|E%3Rr zUeha&ftNI4C8IUBYW)y5r+4$5)LTRlOljb+(*s>lk3zA}yp{4aAT1#rIw!4$=_O4K z`(m|BAdWCh@yQ$2i;US*pjmoxug@+~nP(t`u8Zb8#_NQ*?-}mp%%hgYdq3aTnA*G( z_+4lLF_(Ua+&eUqA)-hU53W9aIK~TW9T^4Lux31a`yfRAWBz^9S0`FZsa#qVFM~fY z4ccoCc6a?e|A{EfN8`xY23CSx{7?c)-RiIeH~9ju20_1@^sSYf-WfS9;M!*@tW~4Y zAaV|ui7j{G$L&Ok2u9Qsy+ED!do)~#g4XGsN3ZS>BdyG#9MQPG=`^P<)v0!G!b!uRsq zN9Q9y4RKb@jV#39;0P6fSfD+CPn#7a_|l<1r<8P74^&E(%*{_!z2;+{{>lQ`7>`oF z&8V3lMfpXX(mY?|L#{Y5QrYF~a^CIeyl+3*z}H0|ZnonQ#8d&KO#b7r*TTILSEj9W5B7>PwzV{>Zw#uj6CG|GvVl-7ebQ zSDJ5FpB!aI_+Y*|J58F?oXd9Lz{M~^u69>adrRk%UBoz%&eeA!FUjcN=v8rDs0U+g zCHyC!S7B5HlDK?r07u5E^P%bcAjPwO6c}?xdE*uD1JCHb`oIoJHZ4Wr>8;p1$=bi9 zU*!sm(wcw6-nLlyGtmC5XWN63Yv8;cL2ve7*iQ@R(3kEp2|&!y+G(*`Q=E|;#IY9a81E}Ow04B%gy(j{@rOr#zKa%Q=)dS zvhd)$21J}hiK;p9IZK~lh(UdV{&`bD0;{W7tp-Ec`fSV@u<;z2cC-eJuaya4p080e zKem4u$10utBc4q!KQgZ1i7iXC3G8rZaE%1fGfaQ zS*ZtPzNfufE+RQWzs5ITGKUU=&!H>bEi0wm&zlMpCcWK!Fv4?-Y2||ktA{#t&5#_q zdE{Q{qI|}I0=OygXVm89uj4jcTf^WFIU=3&nUS0Iyg51WB+-fhmn1`P#SZOt=JdS6 zm`#Ga8b~lS&iVg)_ctctNhoU<=i{HIlZA8;{8*g&;f9U_8CBk1SJYVd7`Mx^f`jw& zbPaMO+DOWNSB&}hTQM_nc}U5o#wB&>`cIw63Svt0kn%Fca9DWhn}n;0d>v7cdBfHI zFU{(KqotC>&H*UB=mxp@Y=aEep^}!NV+f*2q8e;y%8tN!3;!T9XRahNBQbBfD>f5L zYEGL(NTDdI{S6StC@PlI8T?|4d^-ntp~>YE=)y}URv%N{F-5;WWzH`I&|i`U9^2p> zN(w0F#U{WN7lHpTYUx{xYG>0N3Ty+o=X35e2wtBGPzEwXe@cYIM%?%S{y@Yx{EW+QY!S{+~G|a71CJ zW_aQYt6z0`gQ$P#OE|WdM4EA`IQhrHx_Vat@{3W6Vr7|<9<$85?dK)_OW9)wON})L zODC_SUJWr~o=@LoRz!$FwoTN`P?W~=XUq^p$M*>eUz3+FZNXKFDkTPQLd-nZD>}$i z#QsUbaG(mb*jHr}0edlGgo|b@srKH?K(V?KA--XsQWwHH_8pDSS3?OBoe{GA)rPnXL4EApn1+gR{26YcH0c zochud30lZG7H_yeosv=N`MdvGCx-&r);S=ea?yRYbKCrXygGnd7jyGiAx$LOYlesY z7aeK^QvPqh;tRRgB-5BFDDa-5W&PVc0JbEd>eHY4FTsLidsmCo6n#oML7;%~?qC$s zGiO`M4(f?{+Xu~%_hM8C9C?r-vCWntab@HGv2(q%#=+%#bdnUt^(JIPG7)Tclpi{O zHcAv(Og!&D&Y=o)0sk2^Kj|*BQd%Et0%%EZ=kI~bTkb{P7|I(KAc8rGKMIkB}&Gcx@aa~OAu<6kp-x$Q1u*~3Q zV^O`R?2?Ot_fvQE2yR+!eHXBV8~o>|^&4?8ug-)%T>d_$Ajp~ke%bs*g=h57Y?`g5~5a2J&`Y?oOpzU>Niu#~GP> zCAS84x~x+Qy#r;&<^y;rHU+$3?UEKAAORD1gW#=uLZlP@#b0{2my>z7{S$7M4^+HgeoOX1kI|gyKAWRUXC*3UtUx`(jeD3>dDSE)45dS2wMUdrT#~pc zrEB|V81kdql)~j@Y~gGeklzhkv}4%BJ5^$k@IHuX-Za7qgj)C^bvqbA>e8HJf7<&v zZNT7=)O_|X=Qu|ci@z17=FKe{hCS3;+(P{&?=X&AX6BdEB|O=IrboNM>HNR;g4y3s z;q>wf{dK&q)>CLwrfRX(DLp-!T8nlDcVB>Ca<;x=139-{ymnQ69T09N)U>cU{=F7V z!YY9a{r|tI^hfDhDn0gzl>1a``U#ZVdI|As29mv$MNAG+*bf03qxr}21^B<}V+VW3 zqbm98qbFs`QWygz=3n^?5KJ?fnfJQ7Sylk!C^LK}J@SAVfw>jny{$FBy{Vq%+5Y~@ zo33MB9W3Yphrp!&fU{6DAIbM#&Fex<3dqOIN>X#i8i7y-AP&dXzUFFHYui60++llz z>(BHECGJDNZ|9rlvg=O+3$j$+sAzeV=~}KCLKq(*H4pZ@*21_an7UPCtwRiNIE(Lg zlL!JuiYa1O?O=fIc?8oh5b+1^C*1D_rpgU31!gm1E2^a*XocV3I2xJ|d24meP?4t- zueL%6byGUG?B>p*+W6P-XK}P@@0U;d|Dx)7800v!MYy;l*zRs%ifN|8;_Tax6nU&S z{pWZgAxBLYcdSFXl$7SOORhv=YHV-AAF23{=7TV!2W1`y52{8Of4zT}ux^krZ=#kk z|M=ar1Qzvgy$J=M{;FfS^P|Rs!pX3$LFd@%g&=2LCr{?Fx@55Ty0!}Duz;rZY&?1a zjL)WS1GoL*$Xi3ZL>AZ(1Yjz73>hwkqM*q{fUbmG1(g$v7T+St zCCmM*hOXrq;4S-PLzhjPF3V>wg|B&HEMdd)>S{A%muHS}N-qqt zFzi6``4bg}-okR=_*f#POm98x$EcPfGu+2rhy;mwm1dxYTeLM;`WR?ZWIhZJn}zbq z#K3xD;WP9e(`++h(MVnqD6fmZ)kUom4OzteDCT>yM;UMVwly1Ymdgoxq95Y4H%N>Frh^f^TypW^c zMe{mM`%E9C-ma$_xI2Rv$;?^GpIqwid^7F<+Rpnl%3;I)EBxPwbv=W4R;WQdyQ+ac zqqc$WJ>>)gMrFw#xAUW-AO+`SM}=CKXV{a4R($rhg0t_ch*XOe74v+vXx#RA&X0rg zyt3`qlH@OC0loUjb3IustL$}nEMo;h1wmQ@i2Qkn5F)fz%6Gd=D4A?Y9k^J2sU`(i z&m@{&qx0ch9jF*b073SnDW9cyX=YLFrED4$ZpL+_$*Dk_>z0UasA~mk76H+j`b)SN z4qP%DjYKNUR7mT+<5{nT>rtfw54_I$MgH$Zn6`}FKs+wknT{!i|Y z)(%>BD-m}0_ZApkYxNc%rI_|Cpgx~s^Ta@N+%(SY6bMcAyoYL#+`XD+$MbdfrwJCu z>fTS`2D2~!B(oR&o_ zB@&r%p$BhL;FF*@KBa1jMOss|Aam9~?F4hbPTT)D$4T@r+yao*Pcm#88l2`0YB~hc zkfuNM$7S}$ux-JF{Yjj2&jv%)x@C6O;(yhJW>x-#0{3xL{R}PpR{4~>lKX3|i{-;N z0Pr`6+c9oAwLhJ~S2|~`0bg(kEz%~jfmuj9^fhx}hg-OgR^u|3ObXnW^9zG6S5{xl zxwAjEbUL3qf+fpCY$`Aj*;N=+HmlcTg~u2A{&q+Pe?K^Ht6V92>s1Gb|JIi;2eT_Q z2ZV6$wH`9{v2S!yh4QWAvm7&|1V^<=@XIdjiKb!7>$OlRKZE+%M+qzPi`9fFJ(;*vx$GjJ39@L|XaV0vOHyxDyav zKJ=vn|JX(S+n~X^k?Qa5N_RYVxwkBr^Mh(8l9*mE?n*G5o@gDJSn(Pc>Fe+qNGUy5 z$hb0yh5=ne@VvLkDe-#%7jtXgdcDx$y4N@7(%JWT?a=5AcH)!6o3|S|sR>G2|zsH4PM!52Jxc~S>u)v|2vEd9;~SUI}&ehDh-7ygBkMRfUw$47GP#r}mti zZOYx=6M??Umt99^#Da^pIZPGHW-Ykx|6=3LyY4yo({m72e0Ap*2_duDtx`&>mk=0= z8q^S^d7GYKt5`D^i(A#6+DHof`tMsMuXhwg%07X2>&2>G!M&tZBjHLx=?~KY$+1VU z-Rq!UU&#|u7yRV8r9zveaL#l@+Wb^jn$l>Bx%@=Bxh@lQu*h^QSpz)2tPweur=ec0 zKGxFDjgQz1ci!GrlqxSH)7zOt6&>K8P#tcl0~M88O8FT!Jp622p;e%?Y(HzF_-}j3 zUnRy04@@O}m{3#-@%F2mfiOAX`1oT{3l+S64lY|7*RQ2+pUcc!^p-(ptE2 zxT_>mJsJ3`u7Is3RDH7sxKCdEzxyQL68NPu*3g#=jyg@b)U2#l4JIR7g%O2+w2S*O zB9a;1?Va&a80*(47QN|WNj)b${9;^@=^?<~)}xYu&yRn53=~tE0OGNY3GH0}@uIYw zQu{fz9lhiQl=o37SeMA0Hpt7HSpA8qUjLFe#Dcln?Q#N9$ZJ$ly|ubSJ~Z6@P>?D^ z3}#IQJMQSWnyS~Fyiwx&g&b|yM{1CmlLM4XdLd}#frVd3XN)Z#=LoBgf$2P`84q-l zt>OSttDzvGoHbTIrB&=+aQYxuxR56uD z&+&(24C7~Vu|kzQO`+QFO6ZCrqVFjcI;o%_7T}7Z-qd+)N({#FLI}`9XgxRJUk^ zgqxSgpuAZ6WcQJJ0pqtJgl`&Tf(3Z*0INKU#A)sU2?TvwcHP{EF>xP@d{*;Xuu^uk zxzy?D5A=ISn+Hn&JsA-tjH`{U)zP6oFbl6+CpTZ_K8~BNo;Y1biCFQt99`lGG>>+0 z53o*n!o}tvq#szp&!|MRGk%A}e-Zqlc5b9jc!COZMXeR&Fz24N)44J8k1>Dny{now z)(hPPXIHAxNP#?*Sz80re>XKL+chn?9)>=iTIx7x#&4BcJ5Nop)xP%koPCtfzV%r; zq<(~1)9Sg|SkcpP=lKuHwZZ?yEKmComdIl^&;5oLl75UW5_{0(XrU{@-ghKP zpKjJqt_z^7k^<{59rB!HZ`5A|Zbhorb8r3@3xG66MrbxIyejZ9F}beXrpY+*8r#C-=BKVB4R&SL) z;Ntt$_r=3^2m9;CL#{JdV~(rR*QsWp`24F9vdKF5s`Iugd=uTunol@VlnL?q=JOK_hvW`R zmOJlPaMs?n4o@M&UhK8vn>e%Z_%i*2q1ljvU(O&UN>gQ&7W8ZK$aXjoQD(|pVXE-VDSXoeBbyZOX7aB?7bASiAYe0D*3`O zJQZSzX44^YO7d&jhC+?qJIKo@V3TGcfHur8(Uk6Uuxm9fK1RixM+e)wmBB&JQu|$Q z2hkI2Uh|}6`jR=qmzmtSV8FVTo^7_pp z&D{yA(HnLUWlQ@8Wi7XmFTWADaX4UYm#8M`X_F}|k>Sg7UYIND4g<5=H|d8m4ao}u zEy)X6<59PN;tis*8KGp^jG8;uM?aY~A2U_gOCsC>>0s9+Vs>{8Vfo09XqaU#+=d-w zhSlN5jDO?y$C_~ak4fgAjhb)=jDJwJ#$PS4y7(4nmh{F=jn2znq6SFtlsq4WKihF+ zDw7~c6aO1Az2ho|zXT<=^W^+|5suPa-M^5BVLKedsd*H+YBuCW@bc5~LkwWS2Sz1; z#2eOxVOMJk+$;(h4J*=oS@!8JzbugW5IyG4ZcW&?C5!gQDN*^?W|5D~fR)!O;6X$+p3B zB3M6bV1Ng_2p9-=s5TF@@C$j;eK%0aje=P6{TCt0eWb9&=_HFA0pSKYTN><2<2j1H zW$dlj$hZCp-Yazf{ON6+@3%x%if!4LbRJv%&Z3ULfoY(F*-l?h*X^`6#)5ZXZ7|`K$jo8;R7;#(*sQ~2?O7LrCY`Jb_l(eoga|zHDt<|f%8vqL= zL6bvLzz??mqE#S@0hR1Q1h=8;r<>+mrVJ%s{O0e5;~qk zX7fwy*I_7@64jcHfyhEt=*C;JYV=n9_c&D~FLr6Vt<4y~P-!*8HH9Xn+jW8g7F>67 zJdD%xA^DH8VeiKY*j@+rl&rgYd;i98Q|iFgXCI21R+Xy)oFMFA-@lcF3d~9hx&U1M zvP@TLjO`i` zq1UL0l{N=NNJX`qfx+am_p{-O0B+znCL){Io$s8R@_7@WUSw&5({wpsv6N}L%=Kd51 zp(HNSMza_hJyWq!4?_vF6u9<WGr?RI%s&-or7IIQHU&%s)7rDP2{dZ^V=jq7Zzs*i zjyUm0KGTthnvFF%qCj5nqN3^RiOukMyuK36#nyo{)~_4~5)1aRdK#isdAy8Lm{+zo zn?hf5nb8&|YtrYESKlZJlhOs8PIxzh!xGHHcm7codagpgcrGw@mq`p(**+ijcL)6F z4Il_JaYT&`vvy9KOopO;quj*-wf|}jaqaVGwm|W1F#E8H;cHt}vbpY>`upvzC!%p{ znyn-#hNyGKS6W+xp3n3GIQ{M4c}mhoGj!d?681<}sSg_vSoCeu_Yh z9lK25L^OlullQD*Gzsx4xZYw|*9k(bwTCWSeWJ4OumTh_}mv*^ndMz}hh#Xw5YSaZ&D{XoYCnCpe%Q%|XqEdYo!aIbbR%f*hx6IN zq!FbhH~#W@BsR2H<)w68149$0okf^s@zdS-4c!q)d)70H%lDDLFZjwZTduCG&Z;;{ zu|i6TwJVS=ij>E-XBRL|m=7Z=*Yx{a{T)57V|bgwp}tm3jO}}76yRhgq7sf0rphL= zqtw>7;?X4jSc|mOYihnG(nZHBUnfFLle429p@*=-42Cg;55GHj1_pnm-nt@ekl&dJ zF*Dh{H3%-g_^i7?1-e~qw`>$ZFoKwo=!!I5eqTz>%yLQ#Dg8`&(o1FjlUz`FCeh4V zJW}9=lArb6q&O`pt?;{57X(c|AJ7Y(3*=uuNaoKf_xcOMlcT-pP5EH-epA87+|P0V zY8)&pho48^Zx6%_VfsWGD$#@KF)xz-VJwg~?o(m&SySODyWdtqzi6)r z=9a@3@~M3*O(#jryl7+3Jw@X9|QEJ#oQ!_x(8%={-#jjru})2y|8iH`unE z1ejvIV->qW{hjtDZ!WN5k@sno6jCd75G=MOS`SvLU{vEvPsn3WlR(ty3o+?0in6IM zN+5zHbEG{V1Ree`JR=<19Za?)9UO)QtPT1(P{LW?+TCFF^QYd*>3S($&hDP`>wP`? zm)^F1IorCjrx;v8k|4r7zbC+q-D7smock!i=tW&BK~qKzLy?3?u>87JapAc7ntZ9J z4T$Q0_($SOGQ^a*jDxD;!c2j`Tm>Ljb6dm=gjelTm~$1lRMXnBd~~~P4nsljJX890 z{nWKFtbpqvy;=N~7Ko(axz%xstxe5_`Y>-h(|pfA*WKDp!o>wV7RT=S)T<&fmEZ5M zUdQLDH|hoZ*h;!V`csA(+%L1rAgJc}aqP(e22iYbISuT0jbxCTGwZwEDwr_GRKU)? z`b7+M(x2<38$nXQ09Z3KdDmrJvTy^bMCwKK5?=N6RP_^lDt3t~^JLbki9S-60R}AH zhVpO#77b#K;Ysz%%#~6w7xo%uh<@v%Nd2m&DE+U?xB+pbYmYO?l8+JHX8YZeGOob$ zZhV0!L!8}QYfDRdo26KqVn7fj>syx_t;ZLJ{;Rhl%X`nT+r4LF^`C;A|9)tzT?ySj zz&46VRSrr^wrbVCujQ+`+NRJbDEpCz-7fktx0frO3uQEHu zJ7>TwpEPeci)|BW|F0kEbz5yH++UaXSIFodF&GQnM8n%iD1&L+VYmr%pC)g!pmfi4 zqi=3-?r8a&=Bc4Ll=>0h?v;;>Y)a=GRtupp1y&yOY$!cb;#BZAp z560*U^IHwPIaQ4v8G$}!EO7h6Qe9Eo$Q(kXNyHJ#!}7t6m(u*X%!firmhD2x4cLob z|HL|f$}D(KNS&7yXWn5KVeH`2*v3{dP5}HJ<;Ic8Xv3-8K9&G_ ze&9w^uGQhPsUsHj{CB*TT=SIeou8jPOSpkKG7;+{9f73E-qcJ*(#&ENe~b|8?!EsK zJNQ!Xir)+3&*1mcJGfJTkM(aO7q=OgL$C2I6MpAO`ig`4ud})h2ps{o02cbF(hxZ6 zi!m31*X#7O-{Zq3a{fWnN}R*quR?KxB51k4YK#t#Ot-DA^>thYO1_1r$o)0%bo;_N z+H2V9@*&;nDR0K2L8ZKRl6A1Z+%_E*t-GyKX4-{Ea^>LBx2Azf@^rwolnb2${FUN^ zYBCs@BcyZsC}{<8d&dh;Cm?0W1~K|LWA}|C(}xO|B`D^S!q{y=N7ZM)Bfj zD4&Hv?vA+_Oqf+CN0?c!cac$lr&a#rZN0&B(zZTK2A1$@2bnUCx_biwv zw>&2*b7P1FKhy{)7esZE4<-vmaz~~*@7@uHU>$1V2zm&*rLtp9paUjkbNAC)n!Cfp zGCG(t8{BV9kXRU+D%&`pcErC#nD4k##hCq564qnRqdBt+{5I!iSFgk9&wmgJ&U37R zRaXY`>4%m0$aJPp8iP_(!e2>bci-=2yQ)$`|G}Pr8@DgqkkV>!=XzX~vs7LcQQs6; zw~18h$rQCwvZ@*#Zd|89g3@m8Fw$&6Ie;MpFKA%2BNcFJP(C!jb z;%m%g7?oo}P)Fg+pJxUP>)h|X?{uYjA=x$lqXy}!&^0L+$65kONm8()k6E z1hxC$3u?6&3c@(v32H<gXdk)0vB z6PO~|Sp7Mz{2sge=fVTP3MCTfA^J53fa;$0E5P!p2ly*}V8NOA`$*CsB!Z*1$$!)ZTR5-tcmR@o<~{itFQ^dLiYlKWQvR&eqn(MEl{b$yPW4psqp00tytl~VF# zXT!=hGr^Y2<-kwGuT2#=#!8=Gm_o!9U-H(&02@dWH{&T6rKF={6QOEyFuL51oQP*5 zgae{VqFJAK-;gw>eY%c)VreM;71CqX_ty=%=Af3)ig7E(3Ku6exN#0H|?HJ3@jxAokJUxq#wm0@-H4?{HQy6b zKoC--Zk~PYiHrsQ;l$2YFkWY0*zCAtK;hIQCj!j&R^RX&y;V9z0SGBx0`7$?eGfk` zd0#N3$w63Ie^%RYxpL}v{7Pzu1B6GiR4k)x{gR8OE(3@6OE}cl?+IsZhY4nFCljTb zt25_F3Mxo{#Z=PS3jO780HzGRlD^gmfw9gFE|v<%xu4@pLsoS7&26oU^R>-NEu??% z4Y{6|-d_7Kxh6bYz6pz8Q)qf7BSuCN=ANO+C!?F|Ikli;TfwZ7BgCTB%K*tgUSQPK zV648~D)a7ki%fF8yh3!^(3%dF#XR)y*>6?WSR!+V2#)9}VpB>OE|f>|=K!f8iIIra zJKZ~!xp%?B-`J15y;)tEI_wcxfdOK%2(!e=M9y_un}$yEwh$IKP=|a!(edt*kJ9w_ zMuA8c4IXmPvK|BXAZ5J8T;7H5&)$Le#1;UvNbuK^ccAm548phZJn|(#$O)eTZ1H~B zQUioDC6IvJ1S>^kv7@WHUhdAXpJeTq!9~MOJNP8d8_96yC9TdhKB#~eA-Fl z;N1x2fwX(YbMf9)LKc7NheZgFsk9ol>XA=HX3oc-1W&!`9`>ltf;4JLe-}9?7sy8d|DzyAGRziZ??4HUQV9|F;-A||6$`IlHwzVxC3-T zd{e6-clt*3f!qq2@sSJx-vZI!$<%$m==bp_fiRREwRT`dHQJw*vKHk|w-)vFZ=Alz zpTpt5_=9>ag#Z0%lFlT zuR*R46r`4RkhYUwCuFW^1%@#Xq~4$yz6w0M`6?`#m!-muN$lH_cCNr(n2X;PrC~@3 zfNE8|j~nn3*SOoZ^@heX0E$W<8->!D(%v|MKM9>sG8Wq+DSMzPzH$2LGrN&+^oX>4 zW+1KLCwDD%HiXL(0jdqMME-fm=!Io5(idQVqfag>`Xw0-jzUIOQA7WLrn7ysj*VEi zVu{VYQKy>_5KN4_U$ctk)2F$*(JcmZA7*x28IYkrIX&3xp;9=NlA&^?kQa7TkMR~_ z7ZMI*94*i>!q6+QADQhI06e--)XBRZRJgGWd%C%Yey%^((7Ln_12L`Hlonu{ZX6p6 z`NG0I-=~oRIDX~!KJk^~?=0F?w-+Fp__m{8wb z5JYU=LkXzojXY-AOK;G9{wIE;zy^_LTG&KM`6-U+8MCo|ESXWX2d>Dr!|;#{T%lzA zlr6XXRywia{?foXB~`fL%`y(ULUf){wyS!_Z^E{XjDX?5U!^&Q;01T7(l^-MCtP zj_~}$SiO30OLt&8C&G>exLZ{ojkxJe_c_}tjs3%vEYUQ$lWIyirLaZzK4<$SAb}kl z=xC)ni6*PyU>KdCuK>>afhmH{`!tPm^&kYXq0r2!norQ*0Sdf)T~hqRCdcq(h{5cL zemDRzMn1@5YfmIYL@>=VRs3Yl)kuU!+&h{hf{+uQq z^ewUAJ2@MSnn_eEL>zNTT6|xUR(pl&=b^ulW2+sDXMipPFr5>~->dSSN!1RIzAbGh z29+w~N39l{JPj5Ak)KOQrHKa;qhmqQuGXqgwb~sLo8D35V{Zt8b9HZq&~2+D`$>)K zV_!4cNSp+EjhBTEOhRsEf(1Qy0U8Wi3F9_+(oLPK9Zvsl>pK+F&;DpGVCADQF{f&U z_Wu3@KFIw0r>V1zH8GZc)?rrw9HtSwb^8HU#)|nfM@KqE#|Ke%KA?CBO<@PFYEEl$ zzw5eu<(M0!5UM>*S%h4BYgP&JlgNLRhDd>C%E!ZZ12@4|t5Ze~YGT+oXQxoMZnKr{ zG1}>@32-N8U}oP``3cY)>%?qN86@F+M@f9gXgP>Adr0nRO)1Vk(^-u;P|OFWJDwQ# z1~c1ShjdPFJ?p`^LKuSdp_g)sTbD+$$}$M(C2AG!6%sZVU|+>xoUW5gy~o)c{yB#W ze-F4-e$9kSu1&PLAiZ|D54yJdfv4AYNS*bhz;)z~+~Co;r=H!k|3`hdx6y42fl5I& zcC=Smy!x$00+lPyohhclE@Qx0H?C1r>k4EY3H**`w%m80rs~(VEWZp zYS|g~d1h*z9O*1#ArY0z0OF8G{l#mhtL!nXDNr?-F4{Gh04i~I!PwJQqggnl{6lWf zc??#C)^4GNz0_jiSSQS#s+^pIHaHI80CTap8pyqs%7mDU#8io>%+aDmnk$`pxC7n- zCvWY=1(K;Q$wHse8E#nEsl8bb$N%>v<8Tx+SHXT4fxsOOQLQ89u+CYND5%^MoHApW z)P_gRA_{n^|Kldtit^y|U zu_W1Z3AkP{`;oqMh<9@6I%U_dr}bI$#}Bd=2AApr1hS^3BiiN_KebI?5Cye(kg!?> ziLzSX(#w659#=fS{{vf;-ixiJX~3@hd1HLOe4kR3L84X+!B}m-_6n+R?W97#LKp|C zd6=hBswKpHn7m0`U&U15ljWUNM#ItvLwQ^aB8Vk{B?+1y@&X%8z)MQ9+ZRDktj!4} zEX9TnhNRQFsS}AOh1IxXZylpq>`#bJM&$xgFJ*6 zng$vL?ph)))$&pLkG<7l+e#hu?+%?2q%$r__=OH{mSnh$MTVgDAb{0;tgTHL9MO+5 z6bG_jRpw>4c9m$g7k?7?;jcC%M#tZ_GU&U;ugkzZ{){RSQ5#^w8q>FsBW%HzenFV= zvBFRai?VLmJscBTCi$;|6|`RcHV((vFCQjMRYg8oqN51O(+b>@NW5DPpYzZmoR=zg zYGZ2w7J~l|@BZQ-*O1932hp*FURxfyEBP_;$cp3a0?D19UrflJjh9|Z;(5X+_&X*Z zORiCR=FBL)*KfOgkToqC*A}orbLQXMb{)nfP!kp3k!<7MVa>-P$u%HQdt>C0`LF&Kd^3p{F z`N)_LkwQlfi38f0#83g0w%4hKfr~R2w5Rh9I9*+x@jZ?`^vOzeXn#lQacj4xA0W+O zk8Gyq#&srz(B8-e78yyUcPpjA{nVO1!fU~dYUI1AIVtL-#L&0~R={$;Rotw;9bz6W z2hej=E2vAu#C`}!GM#oI3PZIELbV5Vsvg5m`%ffbPOouXs6>d4Ob zb}u!lUPBrfWX<$t2S2s-CHUWL8e&xH=$s^_5_eRyhX;vj~=K;5%9amzv5&6IH~$f@aMdM|r*_l63f+kGM@2 z!4}OEKECm}gwGnxn_Tu}fFRV7)XUX}&?5kv z(!dcn`CHl|&4Cuj@M&2}_)5m@XT$l2CYe%`dYlnH7mPfEOxi!gnxfQwe z1UJ8|1h;^!1XrIAk7|6gE_r=}#k<|*b-Q=;a%A>holIi5arg{XDg|`> z7%d1v-}$7AQ<>{qS8K~K#iEiEN)#I6DOZye_wfC1HH; zNOPN#sfHTn*78X~sJ4GTe>JVf>5-n7p`^YRm|1fodAs{?)vBYADi1*~Y9L-JI>QE& zbr}F+Y$5-pCO}AtRaMfPq$Md=s}!~)=0`6ssxiOB>bUI5B){NmE1lyOINV6WcLW-= z*S?ElruUiK0kfM2IDJvD&2dTO2z-1p^q*&Ltwi@H1+OY!HskQ7OeN)4DA|L~uBZ#m z8o)r5{|oV6XgWet650aE=pR7#vC>fK(gDf=v_));E}p>{Ym`FEald3T=NllI!Q)zp)%i9e?oHfyG{i)$wKNGyt` zkLC5tSN#+8FdA06ak z22hcK8dG9ag^tF?tw(aKtII9&zV*Bp44c_IrmGmM)e|uZJm{TCBr+}U`q@w8>ANJ% z^VRtby$4U(jHwT!hGAmFQK>(KGc9*)jx)=Mufunj_(OM=M~XYqaKK7Rg^a)o?@6A* z@lvR!=g#N91^Nj>&cEddF^Nd&h(JU-9Ex#-o2M8=rbH%mx&kG2p}Y|_MmSZRX{k6B zT4ji|2%|CYEk!KCGs{9#3IjovM$!i*`hmApxUB&ek)zj$L&}H-$`K7$X9avxW6~i} zQfw;*?H(h)7i@k314eSQSG!^FuMDk{m~A_r3=O7!ONz9U!?cD8hP}wOP$~^5eqG8T zv@F;nghz!%$9t_P832{fKai})8rpho^Xdc92nv1FC&~CDbIGBnoOshx0aXOg^(^s6 zYwlzrFl@?KwQXuDK3rQ&apW@O+YHptqc^)5gzPwtjJ?-niiLO3tr7+dP%Pb`9F z_v?oJUc2)6L^E!FSkJdPa{eHEw*u*DzzeU^+@m6VA?c@d7Pmsa|JqgWN=(Y>AxPTdqVRq?c&7t%Osa3k(BG(ExX*I z7c6Z3JruKNb<@i0U$;fxmI^(664;kR6@Vz;+ugt%z!g_8X2N_@z>}9K-!lkK%U7nW z3~&iWOY_9kWfI(;8XQcR+M`&@R@uVVFz* zX>2-w%+DRbncOs&d3Z`eF%so`J>KkG8)X99zFv5+y#p%FfYl_ig79(7%b@S6z_VzX za%>WqMF)!$abV~n(=r+GIy-4_Sm)Znv^if+uaG_a%QOeOg93A8fvp*^duw7$>af{z z6kT=3#NH<1-Z|3ObAR{1^EAw4?>lmCcWcsQ7YlRty}E_q?a!5+U3l2|g#F#85|a0_ zdV}6FYU<7MYLP(0>P~psbcSl;#QBN2<4C7$MLf{wlC+l6Zi7OCh#{DngV;DpuikDw zT9GeDC$l(F3u2cQ#3M?R5e8HhmV1vBBT7=1MT<{Ebt2$pudA?}Gq>%ZyQK(ETNxR;(@f#i&{B+bqT)2>$u4v}bRQQ$m1{w%8#9lS?ot3#O~ zY>t5wCy@PDius^&{{XudLxbwKJFf5FmmO+7{xlJ?&x;x{)0xZlHN?IBxBAM&O_53+Q5Oq>6HNp8CFAs z-ttFvy=(@p49m3*iFtzp-LBV1GOU@h7P%Q6E4x<_#mvFGHgR0$lr_vBqSB540fYcq z>qwmCQ?}*ZIW_U8EddSAe^r3^G}EPghEq0!{2MdM656ldb)hD!$ug`D7({KFS|81@ zloVD0{s(394EmP)lCzdWF*dNJbIChPSKF3FgZ?Ly za7YaL!L^K(@1d7eZ_>rXUCqS%<4&Em$FSrssdJgY%Q2DjjbE*v&O489p?8m^I&Op( z>u(Jf>ul+DF(L5>nl32A7AyN&0^zi+4*Dsy!naN`xmps$JNEQ*=w|(uA4*J&lXbS3WNn^ z&m{74GO--zd$j!iuA7ePSk|q*KR?=0cRXPjpS1kDoS_)C5#M`sSm_qMD>|8dym0)+ z0;c{ZbG)1YM__b-pA23X&=pOWhW7lp>nvmV>;!pLVL4vC+O+pY#&K49)h{fhMhrzW zm6`uo>~eZ7Xc&5~b+HsE%(S0i>RQB@D=`sW(+%yqO9%v34l`3}CCSS8dOwwf@?_xV zFQH4kYJ_X7~yvSQTkdigK8$wxo#Mm_3(ckiLYD#?_*<{kw&29l4;?e6{nx*ku- zHY(TkH*klE^_0sRl71d}u;2d-rJ@nncX=T+r9tm{P0;;c*tl-HW z9wI&b(3xxjaSG30C_c~2SY09$hP~19gWW@}H@oNRpuO*rDB6mQ2@-W0K*f)rRl0RrMBwwfuE<1U^2uCvFCYY*&!JCX``*aQNCq_9^T@1R}6S<3N zHa}e=QqhztN_s}(-~_`s^cu<;e0yW>&{Hc!8QhrE3}u673Llnt%W|vB+g-cEFAtZk z6?WkIiBn=huIjA|Q7urN7s9evTfAdoc+({3C%BQj^BeDd7%|uMC%eo|X?r?;wK|gM z{=U}>Qs(Nqjarp&h-{`a+x3sgK6om!tt551DtCL`cO`=-`F;v*5!rXQ+uE9#6Geqn z&E^!|dq7JQUO~ZXz#JHizRtCGrk{BBLz=pe&JE=r(0}Q|uy*b|qGzu+A@a^%sKwS$ zYcrO%$5oi@sRA+DZdf1g-od!MP}93|y$Qr#V%EVF+@A(h-7@eJc_Q0~=6(Or=lLO| z!L6p6^ObQ{rlxfB=N->gOT4PFyxXp}`%f#s%0|E2Vj4w30>KBIdHWJwJWOw6IOb?U#OldOMuv-X zF3mmr=QO5th^DCpfo35im*V<-5olmj@))e`(^vrS+s2Q2Os3Xo2j5TnJ%8+C-2Qry zi0hI(r4PITdR^`Pq1l}W%+?Qi@Aif+B|YDsZ8p4{DQ>VD7R`|=l-A9jk6Z*7z%_yR z7(>7|sul3~r#RJm^rjP5sGxy7uUbR6EmR*_%-JAD<$j=n9KY*Q4k+|;OZnN#n=h8p zm5K~)?UcOG^P|}J*x|!zDX`xevz-`b?+}`6t^;9W;B@7eXP{OrDb zjH#;ZT9G@E|Mz>$FGh3K1=|~?)ptdehKv7?^lSJrFi+%!#p&2C zeva6kpDz#6N=f9Dj5#ruU0e%bfM_HLC*rmZ92r{uhu5QJu}XoRQI z-bg|jD|7mQlSCYF%9`Eu|D8S`-ZcdNJDIk541u%>h`hx4Wqg3FhO%*BFqLiQlbAt? zNl(-0+ohQFHEd4jNT<(>cyr5ZNkmr-YtKNXypPdrB@V=VKa$Jid z8~;y*#cr~y$45S)k6g2r+h<1$;e!uw8g<+!?S#}CMxQ2pT)9HdmY=A0 z$^FLQ8_dy>-0ZQ(ni}y=m1!PL`!`udio`F@I7VIhfV=b)^#xj;NAl<(6}X@`fp{<# zPHoViVcdX6Tzh@R$1mI!gU7|frVQzGg|!JhzCD9ClyII8pV;6a^aB4fny(giW``=a zJ^prbg2b#t0}D5yuuVS6o&fO&v+e~tm|xW>rsK#-P}N(xa@tyKKPlp)L*3c%AJ3el zSTFesa^}0NM$eo>{gQ_UXZbm~#u|&cx_^7hir)K$qMN(_;CcSl8$z@wUDwAmtwU5h zVwxW>{bOT`{`Za)lI~M-P#7gu!o*(7u4Vh%&js+;oy}uFZoFe+uQ^GG;#Ol%wCF7!0=BnR2P8SRDyfXcLMMJipDzY$RyaFXCuo!@(-L!Mzk{*fC zdrcDX`^q#ceBqT~1O#f=bu&nc(~{DRfv);;PZI}6s=-B3Kt?+A$sTS|{o3>frhi2P z0Gc?Vl!|ecpD*=4dVC-{J3h6Lx;rJM%M5#)#jtIJlN`}E}VM$t2&lqu?L0bjr z>zEDYz6&Y!F)n$(=yz9BP#Yh{LR_-k1vVLh>{R2VO*!E^^1E2aZIi@z41xp zRYEOE@GvG<&rC=sEofl->^M0)bbOno4op#PyF?Vwygq_$_-aw2323Rr(8G`6po-Uo zMPMgn_8T6%Q(4Rn`bYDPL+n-mHsZ)ObqV0{T_OU5yTz^de4$3HA5}mJc$#+`M zRx<|pNWB*l=3KQext5x``7u-8rF#NKJZE6m49mQL)iK`Tq|Lgd!@`JXQsQx zY^k}%WUgn~-JI4X(*c|`#J6wPP@bOSXP&l$sSV6Fh*=q+NHP8EK>aAk?m0T9mK9nu zlLCHQg7c%MxdL*pTjs~#zKxQ5 z<{6BBL>lO`McNtkR^Vv9VPI6%>t!y1-_GaHW^#Qq+&EmGBA+A`)z?<+*YP(SPwNaF z4zo56H@#N2?aQ;X*R`K@W=)^S_Wn3zx3FG?+d6?M1?A=?diH-8zNghok!2BCNvX7W zX|F#OMsd9DqJRfwPv=~bUc^+yp&=r|&Dz?r71}-AEK1rT3jA}T?zx*6*zgWimWyTv zFc=UGwwMOm)E#3@hCls)G|jV7_5xbGeCxxfe?O5ae=8|K<3V&o(;~?`>WJv+tZr?Qd|w)#Z~*8)YiiSHa9ZFU%<;gn~cGZaBD# z2Wz1b3WmFze5z};M&dRvr4USv^G`q3=#TZ1?GH6tt!=;eY#Zb1N*ULeO5BRga7A4< zr&k08YFpO$95#K`M{VzLnZW*2pQ&bp1$F*foUOY$uG9YGQ*t(=h8*c*&#%^0=$8+h z6SH9O$Z>fxTN z@A{SiLy0p$P#{A`pecD@eA(lKnsPkf{rZa& z;3|&TYw(P2;H-KUi@kQRu2956VQ|YkW>x8DpI9thFDGP3Y)Tnr#O{)?n$XU#eyGd2 zPYC6vc@F=f<9E!6GikUcXm(f_lM;XvRi+m8OqW)AN`Vr(+pBpcOvygUHMmwh&DB-L z$1wZc9rj4#aGA7R7|oq6Kg_j;D4?&VGW#|98spc>8wa>Fkxz<6(K0QK1n(P(QZm#PugVGhFCuuSnz^;Rh>=b8IwY!%rWDtTN}>y zQeae-uc5@pqPxLFtM)6&obQ}8)APy7qjG`?m2vot(7N9jCd69-ciS{SiDiTJtXz{g zSN%!a{U-VLcvPBK%P!!)-Q{~dUClZlNNU61B;`f8c1#CUb`_df`poKNvLp)!Q&|uw z(4l2t(W>k%zl^9SX>kq+O9GKzVrv9?oCnsAk0&sT+4XR;aFF*@WpFn)0kwY9jUi)* z)XK#y^vj6i2Tn6z?Jz5o-6lXRfmvX8cQahmd#Mcog_g9wHjAg6#c^~8Gy%MH_hzCiV-)VQgSBQPSA-(%3pqB=*2rgl$B?y|uHg{s;b@b6v z5oehJBYU(i)AK{BQJmj9SmLcpx$Pt#WCK01-1hSd*l;gN(+&!id<2XnH-5>qWBQJfIs49)Tgjun97|5lu%W zJ74t0dM`HReod*%UrUGYgs1?QzO-K!P*WiLnK5D&{3ZAzU^KnoZlnGgM1c5*&E(!| ziz<@Uz{s0TtiZRn@_o+N{q`Xrl{qRg7<4|Q$iqz}YzBSa zEfKwI&kTc(WDG0A+kgAu4*`8SST6pwkODnaZ5| z;lFy%h`}&4?A9qKOmN8I<8mFTFsg#S8uGyx^jhs?o?irvWu z`z3fGpg1W4XT_ku-BzuhosLeNoq9hwH!;VI5QSbWv=i&DU2O9n#{}*3xZY!`(k8#q-`NFqsR!i=)Zm0JJt%`8)z) zdLbjR9~{bs=x|C3Vw9fCS7_t-mgMCs`pAy3a7qWhy!+t}>^eq}W;SqB%@1=!Bqv9I zO{XOiogd4*zx5@hhQ4rq8M;ED=_7NfujEV5rEe0G&6co%o^3A%3=6?|#>q-!lpxw4 z(Y%`tQyhM|3{f4X9M|>zZ&cb$PRtt9 zva2>`hT)^yDdHGWK^Sp-zIn;nAL*x)oAnQG;ENdy-z+nCxM(2#Jj&%u#I4#*ZVeqN zoOQhem-REa*N>fRlGQYp(R((S1m9FQr%TnP4x;JHm;ICN`{$moba0T=%2d54DBubA<>-6-}t zUqMRj<&uD>O^#~{#z_Q(ph z(Q*Tze!L*TK}>{aXL=`3sz(Yz=u@q&*Ch{@-;Xj{g5C1(f7;MXwlrtcQj$`RI_UT} z)oc#@W!TiV?=EJ$TeAi$eLBvvmn*yb#i$bGWIEb20QJ5F-EP1WcZ;tsr%jlPb7Kn+ zw@f@Yy)q3oEeOKUEeDrHZ*S{uEEZdj_oj>Q_HJ4YD`h0YVuZD@5 zhduA{aDx9T3?>|Iu7z)W2)9A$bPYY0D0;i8PI9@*I;trK_4@lPKx#1T%g2TRXMLM% z|D;5^9gmE}Gi^WSwG%)#LE>YRR}c`9ih+~$MS(NSl4dL@XDshJLoe`*Bk*F_U4({O z4jVw+BoxPz@6pC3HuL#1-u^il-@7z*wHDMAaihdQTpq1DHlb?=gLZ$zbPU`FRH_Bf zq^AHS9Ii&=j6NY)&$MDPJ%;{Zigt;(?vlb$Ui#aZDZ_%@Kl{*sRd@f>l1z>S*DX{B z9Xm`B=QwJ#7A6?Oc=rZYUGL3VSmcWG84%~lR!Rzl(aXkk^D<}kv(I3>sC&v2e^c>R zu7;H^dzBP*Lf`xQ!@!%pp!c;gCMn}%ZcDl*EP?fXnA{4+jjX*Ru@D#Q+C^Fn_{I6d zNh1M*S_INL2E8EfY!)E`=TggCzqUxkf^&W#A+q`1*5SSrn&(rpQSM5fRfTU%8cgsO z=+xMhOI7lmWt)UE^kUl`ZKRn<+VVGfFgD~iqU+{d*3W-Xs_mid&9@x~9)g>n+E%nE zXXgQZ-N1DwDVPsQ7%rdvkSJB}sxcn&VfNcS5?KMB^SEZ?0`pD$niJ5I^s1 z4&pMt_%&KPl{Mn~SJIJ2IIU!20zLiwCh}OgHc;2T>mjPC+WhNaUAgt)7YTf5uBOM>o=8Y`R-O1k4>LF zLZemyN$)jth5{PvBpw3V$08>}c6#=^+;;Qa_?)>MawT!1&i<2aoJOCoM~kG?ueI-x=+&>o zpJha(<$9y1?}!mI9vok{@Nam$7!DwkB5|W)jma2=_HUP&X>12Ps*H!dDT;YYu@u~U z&l~sPTG@k`K`Qm>_XS>y$(D^F%K7CdW4WsKYaWSvbCiX0<}cnuYkS zpJ7+Ro)P`1=%qDIrSRxZdbHx{Mxydgtvt>ciXnQJXOzS?=jQY8pB!CJvc5+trWX>g zv0(`g+dB)^S`^@KRs&Fqh1wE8mwUuO0x?c3wbsO@O{TW{-KJr3crx$RhGNof8}&I| z`U408&DMRosK(t}jQ|dw_-m~;-W8~J$v}Fw%fB+wPUN{9%bf3m9DqfUUGrd67Hu5? zGR3(4n+LbL=HwG(^OIMRD1OJq!Sw3079bGhSHvQu^@c_!8)6%a#fjb;-p z5Uh`$nVsK%iFSwWYw7bw7&)Z&55#*zvCU6n-_c2pZk1gh z>hma*%U>7bQR7_O@I*OBfY7KivNo%tP$L=}Hqai$1}(X^I1MUR$f;y*n>ThFkPX8J z|JtMeVjd7of}x=n|XqAE%;BP-B@DTYnl+ zsShYgfX>yy9~~qbUGv6rJ`yz-6=+^tWc(m~)`r6}|2Al-iCBFeIBJJMb;qC2zc)lF z9@ohqQRo8BO*3C|1M@-1%}w+Q7&Cy4bhG^Tlh!+v?e(Mw8x|KLh zkx72E99-!2WzorwivS}SYsWUI<1)>UNq)IY)TGs00u+p2F1;S z7d_?Vb7}VYPG++qzt7>P*N+>|g%$@bOj<9~E7%2k2E5E|863%W_Mdm0J&!h%n>3oc zzqN?wxUtt=y1z7a*^&B&Ey_y6>-Z0@w$B=D+#ymk7fFjidyWBS0MeDc`=9Q6_O}KZ zh#`URof*Ss=rO@rC<3ULZR8wPi%tJ`dZ^uNa}qx?cnS+DU<3!ct!Ttv+tN!w&Jsft zcYpum8?&~sO?!TfurD)_2t*=()GC@d3?QjZ%Qn$5*x`<^yl0Ov~wIY-yq}cD1u_aC&~S5g$Vv7DCW6 zGa~{-@~;n`rp}X5DxB6HO+vKoIsk_FoCDx;?FR+b);&-Fob1KjfJ}xOS%Zb{L_Wu; z`>FG`jLZ7zQiCv2(s^=)C{7bOAV0$w$jch|=(goR8FqIH5Q|T9=z6wg0>=KS$52fi zcjT=BMU~YzM|VRUC!ebgjaD7*L>+~Ccq|^6F@fYUGP~fNrJxZyB2L`Ty5Nhw%jkPd zVl$Vb>3r*tGi9U@mkJ!XKmxB#?W^a+U|jKWtJ)m30~#H1H|!!%ZQz*>4hV+;r%Dhw z*T``}OM`ZEF~ndD)*_AW93>|G*G=9yxeh!d9rFQFxCf_ndA0G1QN7r1^nQcy$im3l z@C3F_$>No5A7QXW3yvKq&0?!rSfm-8Jw80xyxFf~eF87T+I_6RG2;9M!))PHVT2fL z)lyeDf(aKi3-29a2&3XAsdIii^-q-z-Nq^Nxj4oJKUe8L)|dmF3$3RgNoEFN=DrUj zXZ2h>cUQ<#23C_Ci^QKGxv3udrwTNByE5mkD)sn+3R15OO@~h$_TD93+@`E`-P_*1 zS(vL4_c$^{t(K#>a;&$Tr(G8Q0Q&M}dzkMo>S%F4 z)b4}VAxgSTDQ-p>7A05cf1HRQyrzB5d8aTRi5+>n_~cs}?%MuCTd)=g2V!SsmiYq9 z0lgvzjG~(SB0;qBB@51u`BE%|hZjJ*xW0|i)`J4wfK6P(2Mzl{3|YNyAj9(ShW^>-4AtaP12^kV&T#!;ws-n%$hia*ZLU34H?bQ|FFz;b*gCd= ztmHZ> z54F}z1q$M=t%4s4GoXEfVJQSQjp4oZdSpET)Zn{h>OS^5k%i5`iNNFFu$i`-RAUpC zRe~+Gj|{$NWUnJCe|(H>nbapjoQoG!t@iTpn5inI2PfX$g;`NqJ*M3mYztvYD|HSh zKoCqeW_l@VK(25`BNKCILA8EKIKF+eg=P9$`tX%F?>xY(`f{V8jNsVW z*Mi5EET0*}0^wbWR{?3|bLLA)UFC&NYqWsu0ogOu1QZPa+GD_pJujyl&x?Czb`Ii+ z9dW9NAXcFh8UUp_#FFWy0WnzJo5flzvq@l(79?N$Lv5ww1jhl*Oepw6kEXVATFJrD z?Y~Jzdr)GB#y+)n@JIRTBlw$#%abqccbS1srnC`Qi&)hYE0O$)X`ATDJGepD9`pes zKKQl5Z~N^;DpZ55KcM*sJhXg#0rvVzG$~k~R1S!u=~^(JizN_%v)EAjz6diM1k0Tw ze{IYR72X0+NCHMH0~A9AKCD(S6^G;{R`=Wnys57C5F2;}gSEv05U&`|97`qubbYus z$g!fJXpKut=VOiSV@@cZX->Jd#&o5}TN{I|*_8Ni?~~+mj5Ck-FgIe}Rs;3v)t3ey zC`V^7qt^8Pr5jW34DUwT0*^-m;Vyq4h0Psxu$DY*nTOcR+XUY_%ZAP5dM04E0Qt)Z zejK<+KE9FFZz*a}uPL-tgaN1YZA% zYZh+qw=%~8p5NV-J9p6&0{ly#o)NUPbWSDMN;=0N`_gk4AfLYXZi=|gwc?=Yme+8n zIVksbSznZ+EnnqiyvbQR=W7;2F_bgee)T4v})HqJn`k z&*#2%FZp)95V|1gk+g_M($a+K6N0I;s`U zGORRyr=CstHYUbh3I8$ZAuxc~)-qPI?uZic1`Oc#7!iZf_!tm>f-e7j(N5UB?Tft7 z?>N63(9{XF`?&IQbtaS@Ri`5?qD;PoE>dro#D{t;{WHtJL7Q4cM8s4lb}I0=-0#jhBr;d}nKQs;1joEHC`*I;Dh#?c=cy7P-WkyXf@q2IQha~iu z#Rp5u_E)&)LE5*+HkN(IZgXVk{*!a3Y%|wJz5Wd~Pj;o+&0AzbARMuLD%G?!-qN|n zeBgOz?dk2`-qck`o7qUutvPqVru-6-)M~vTT{;EkodKhxF_H5Xhw9WrW zpBJp`h)QvDV2qv7ikjJ#aQHzYF#Se2rBKv|g<2q>S@B+U$zHqeEp7mB; z^sz1#@qU)Mr@;5JI?mYO=bqe0tEW2l!(SR$zG@i^y}-6j_UE;K0mCz`y61qy7oei@ z_0rmOQHTB<^V6Z11BJkN;S^u06*DD)G6hw|2`}K8r;nNLWm;o6BTMnJ6vaf*9BkJ! zI_*ba7bZZ=BhM-XG?<>5ham^_Cv4Yey!;e!+H|ZB=T+_$HsrSFVL=AR93Q^7T9@eD zqVLH*k9_vM@YpE2>yvKL9k~H{gBf}QYJ`05^0$A}gc`w^1hTE+ z%;EkbPL0Sof(nbd<$ie)POMZu)%$Iph0lLKnS?WhU^gIR=p` zUxzvLUlrVsY);`@+hq>ZyuMy0|742{*BpBo*4SY2SM^JSccx)Je{nqXn91ENakteT-?Wc%NV1Aw`WAWQsvNl-J|hE>ahn$0 zmsEAu^;=_C(rddcshu6rvYDtusvkwxnYi#;d|u*u4k84fiLVc*UuiJ7ZQOqH>Yk_; zV+-itzp!^b5=ClJoA}?EO%z#C)abFfNB@4aW5ORr+WMn`cLTzxcvDU!#5b{ip&k}j1JS)bNiX?2qNDA_`l`rGplHpre+OfvGkT9x55l9lRV+R9`+6U$F6s!=KLp+nH`zWo&0ZzhC27}yj+?K`Ui~5P|^%{Qa8SmYCg_LjFVXl&CZ1PR?SBqS*82G zn zk80!fcgcwQ0M7#kr$Jw(?&$sputK8K(w2l^fqrjW4J$+k6CpPS(AifUW00F@qau$) zh+^Gj-MML0y4vDMX3>o`5q<)5WmGyf7Xu>=75rC!IBXnvYc9XPQnS_iuSq=`-zPgu zOOJW2c_c_NGLZN`Pk+a-QYP{YY|Y^no#fMQUbQWLDuGP)>xLaZi=Nqe@zW_E&xFA| zgLg{&XCODSu2ijfTYYfx-&~-H{-KHp?GJhCh@q~ENN{GR zUF4CF__Egtj*C(eH{p+5Zu*C23cqba5Cg#P3p)?g>mkI6WboGFHJw)oa$RgrC3eNy zgC!7{oNW-c>&?&3&&oeJ*LV`!hoolbZZ6fF*!CbQ$vdYb95G1rf3KNdAY$^Ts8n^t z;yqQ+Nn0ctoRn1;SWQYCDqne6O&F;_@s-VGn2kn`Rxw;)59jFxYwRs;q5D!teEqul zFO<|A;h?dE<~5V5A({^8+|n`Qyo=e<{fLX_Uw(EyOOQpk_s8=P8`+^kovY)>^Wvrb zcMO%syf2Q{sA>|;cPd$2j^tAK<}~6sCwJVMXN3N(rT>f;QCqh|iyS++X#&l>dV5fy zOO}0KA{jD_-NY#s|7(0QDaFSP#65_Ww#RnzO>=iGo)WT9|{!x(LeABw^b zLVkgp)@@~m-e!j)t+%<%ELwd(6&TZmEQN3LD7kWe7*-zXFkfU-`C${zqr=5(F^6o^ z>w4_6fh0q()11r_IGH$Ui?{UUiJc4g$q(xA79VcV_v8!w>)mOBD|s?_ zbF8<)rP;JQ)N1~T7k2b867FLdLT{RNKSD9Nji)`6{Fx1ch(JOVt7UqnMm=Vn>L9@S zQ$s?~hh`kuOyYS>a3$ickhj_WPFq4`AXBU@v$;KC22(`v*QJLA4RiHm|K_zY%T_31 zBFlF4{t;xQ8N{?MLr(EU9Z{6e?a=pvsz@+3T#Jkhe(kXxO~vFMW}{!kO2^xww$CQi z1X0}@@yF6r$w(ms#WU_S7e2l0@ibsoq0LxMei>GyK6TNdCbJfhj5@%*>48H4v&QQE2&DWxep7& zt?}QvV&NpZMc20b7sx>VL6`J7u`^fBbGcG% z&nG>Kl7k|D1qHb(rnEIMtyqs>G3MhrhW!ctrJUfEJ>YiIMk?@ThN+DdHJ$vq4^RMG z;UvS^x)Ve_X1+|#H26N#o*7Cqd-A5=qtTa$ars%!rQ7vz)J%f0`~a^-Bt(}<>X{SI zgv=LCb}+;Q8_6^LdSlNvnarRE`D>138pp*Qp^yzXE556(;hSqdIHb+>ac?t=eJ;G) z)YfV4y4k;xRWn}4o^?bEsUXlD7~xFmC9qX2F}ma-%B(z0cV?}Upx_ft*&0rFrlm(e zE$QcZ)un={U8C}LPUL)59UPTbaPWhSPmAn+q&PYsnNq267i&1Cia2kj=K8*EYd08` zIpF#x^F7WbP1}Q<8S+TgvTvq4zCpWbnKKr9UhH=PFDP~Cj!5T)>n4qTX5sN6;%g9> zFLP*sTxh=F{1N#@E?)N=%{=((ufFiFw~fhvJP~l6=E?2hA9JhxZUVQjyt_|ZTgNVf zP%oInhhpaEWLLf+JcpW$iUiJ;ZqYUJ~M5s-!da2L9EZoD(f~|^rETiz(B5*jyLf#I^DKF zC582?-p$QM22WBPWKTeEuGNwgrDmNHtxMJF=Knm3CYNUlY}xl~Dcm(*rWSP@uw6O4xT#K2G52p?36yqw2tVVeUi?~_VeE*LZ;aC{!&hA@@CEpF`MShhM2^u4X!^EhWczz>9dxQtYpHM z)hxAxyq_xPebo#KOz6~MWOL^zG8R^QvFm8vx#q)_bTE{UZdUBWc@gN0=>`5TPJzYDS zSvWn)#hw&^MrtBzW~kPTaq*nu$i8y1{&fo( z=%r1g_hq@k8$|6{8y`3cy}n;*fLYocv1Qggv%^mwZEV)^nL6WbzLwUZu;PeIN<0O- z9@bN`Ha8M7kVzgNIJl;=p9lSRE;Rb9md(g!RC%IGU=22R^u`g;>T&{|M>- zGa|sNT6mfe94VSRnEh2zJBd&AmUdS_)%;P(=M{DPf*QCc=PXq*(&n(~R)(o9(P$AL zc69U(xGW@0BX5sGPi=7q5{haHYxsbG2GZ?gehl1=Q=L1iX^;~qFKRZ;w#B0t-&1z~ zF`M(qLkR)hFJ+L{*Zx{x2S}3Hb8W57h3KURTyvcVs){x8&0oE&dLIhrDboiJWmey~0Gs+O#va8yI^o)a%YnG%v zekD`x{gdwf`f`~=?q^*4CcelAwM}LTlrs`~%7-?FiZVl-W`{ zl*IRry*Ey)crvX@KMAbEEeVtmIT9q>SsUM5$l{=CQ%^Fg!Wh&hyBhl(k8`%ZYEjqF z?D(D9)EVXRf^Rc}+5{vov4z~f^6*y$>AzqlFG5`a|8A=D$MqO@{AB)Eei~$qfC;(4 zbVy}%Iw_wCwqsBNS=CcW_35=SDg{cIUSQ)vXNzC~C-IPhvI%6Uf!ky`Mi~Z0bou}_ z2uhgpG0f+n=6>Y=8z{%(W0Nb6L6{E)mGrZrqLXX(RePQQ#{a|BSI0HsM(?VKASfwA zx}^q4DkY7iNNj90qe~^FI|fLz(J8$Vqq|27(xK8wi-2_9eeeC<`^Wv0KlXvWyzg_) z^PK0L^JZ41Nwc-l(<<`26Ga|@&P}$Fpodp=@2=r@L9q%?v;KM5hJMi%T>r!5_~{_) zP19xFaAM^B^Uo|BgZV!)-pJqGoRe!IYac$YX!KN}YsyYm^~(Q(;BQE1^xVSkHoi-S zgb9N)I*Qp0p=e0iLj9Aqqr9nF=jW80{! z*?Gauqolp_xP>FVfWEU!WMZ-@2fqZc6xO~B`yVpZL@U2VX)higH>xP2^ygWr# z8bwtw)We}I8~qGkMx2m=OI&OzqCvi`C!qco$oytE2Ef~*b)|05-xrOM%luEp2+9F=B}yavpQTT z3^w&?X>Hqb*!Dm1>BRVbXh3*)7|OUwRqg7M^KvJ-k~7ClVgKiM1nyZ_4aeV}FnyP| z>gNop-JPhWfrV*M)g02<|FVok3_|3}6wy+pQSfQPg<)9TBz*dFt<`u65X>|gReF~v z{?*h5<2?_bMveXKf=wf^J8{oOo<>qFcQMjG#i)hFMo}p$EJbYN$fA|vkdZrW$Lp4# z?SOa)pCZNA;gjG~xXQfZ<-Li9w~A;A94y82XmC{P$)Tr$-D98wqeqA_7hFM&OCd}@ zZoq^19K_sV?ID^fU0y}$^DO@BdGzd>s~dIY=5x$Z5#CzDpsAoIFoH4ZRu zmJkHV6H+J+O3u3b&p9=lt$6SL{#c4AEPG0W`mSfTi)2b=YC8eVeJ~eRpZ=ZTW}Ect z>0IL>Cjg~g`|*Tup~n9CzBOi{eO(=Z8neC0B(=Lp{tQ8z6b|;7no3s9RVwNdR8EPOFA3z|Y&r_b)Jir~e%qd#OknW$Wj5_~B9R22JDS=+exj3Q#| zT%(N0(!~pzSM)k#NkI&BC|Cjpt(oR__I{@E8e}#+S&nEcV6T@x}Xa^Q;F2j-M6DSQzuWS9r%vU98x`2J$dFlroR;_(9Ni~(dX!63%6n9cY`!opmOiX?CnXM8r7kDM^k)-S;E?y+l)F6AG zIDQQh??b)kO($7FT&?Sr0j&`8{{{>D0#Za9$ip^N5%6iQns42CPl4cFe;9_Ah5~f} zMYo$_E|X`*ZUT{7e$l_b&}bw@bZAscqp(p*T$^ryv`MLLLD)$|D69}uI6!4#(SQ-` z*t6IU(OaR?!Ott>`6D;YVK-Itg`+!8M_IKG!)%}-R8r5*TO?)D8WZb|{c$2DF~gxF zCb3A#TYF5-i{vNG{3-=Tmqm$q0ZpGo>pd&V#1g&c7z$G_&?yG;XG0K2cft=?!Iwtt z!%s;J+-{#jQbp0UJ&rsYFc%$#f zv(+x~Rfeu5fKET-G`?g>@x))yV_wzY)K<53P5psVq^@# zfWe9Z5Tb_8Uva6R#1Ih!hH>kf127X%-V~LK6+n@tGcn@37i^lb>qyAx7Pi4E0kHZb zpwY#lORG;80F`_+NMouSLh4%5cb zO<<{%O0p%o>Md35i3#Y|6Q}kTVu@xG9DZ#1I8Qt5JqMte1_!7@d2qC=bFuou2U*5M z5jDLCVuO^0PgGDXap1Bv9zJlF;{a&yk|hRCMn*$nWaY17S`U#cdU+G!2vWV>exbXO z%tf8W3@%;WVXE}_tv0kS1uZb`qWXFmeN4@5Sf5D6+Xn~X%oi{!a9;b;)@La zb4{o=fin>z9)ezD0H*QDmHTyHV+-3&P4Ik2&#wvV>*yH ztop&^V02dCT&Jq|_D9b8SqOko(+0QX@ouI-#xM3n-2kV6iam%yaBJ2=SX?>gd5zvK z8rn?Y$JJ~*Vhmnw-mDp*MRXWPr1@IS7)cIr>wtLd zezm7chkU*_9eK0m4@GsVKa{whEe!%|+Mr;g$Kx;rHrR3y6d2dD9y$Zr2#=&fNdb!1 zH-@;?OP8PVtay^)ruK+2-+dhC;BV%q**h&=y*$Ft!f{65mCt|*2U{a23CdYf(a43y z9j&7dJj*T+iNx+w#O>J&zi_Lt4m@{jwO$_QdZKeJd}ZUWSt_RK@sJyph;MGW4W0}? z_(eWm#-@wmlnP9D&4W6K`O4+3D4X5bkU0<}^L=z-tXK41`vafS6*lY^`%~^LYrI>%a?@b2>@wgz8 zA^6ZTdD)_T>`)?#3o}#?sJx0qAW@2m8`-PsfQI*vv!w>7vf+p~DHgBDUH~`&Pvk5I z!%V;2V2iK=FA#H-%>6_Lur(5@V+c0;sE0U0>R`8ME%y^E+a8X#N%O0Kq_mX`@H>YVyGxX{aiQ6-LCX z7Y-ta4A2Vn7okayne^Wt{bE3Z<P4YCMWGhKKjWA)mL50rBj*IPm?`iv6gZV3;Bh{w%@QMr z+<^AxO0%+*k)L9x52k%!n!400psYfA?q;6-@|q&=uJ5SbjX_MH_Kt5re5XJog_E?w zxwSYc^YvE1S5|`N(UXtR=ulph{_Ru#bxEZ&x@qb=I?B=q=b+qpjXoUi|55F9mry`E zHq*~bB;vH^54~mXYYkJaD~9&-13Gnwk`lG|uVo{|NJMd$&Wb%GLLhGSD8cO>sTnSf z!R#3>wC_1AG_SiZyuM>I5Z;wG5ZrfS15-w{KVt(Qp=8;V)6SL5u6osG=dFU1*_79! z6vWw4v4v^{it1`_FPKw@ zKPd6YQ?_gfLb7)sG^(zCKFqE6`^6Fdi&aZvJ^AkuH3y?|i_uIKVx_slF#guF%@D1= zv9R0VM=KJODOZbuhPH|Q(>6SfmtV+e^lrZA$Vu&a2*Kw!#3cIu@TQ$|+R0RO7#8>3 z^~I-AG$rmKR1leOi4nmYHHU_D7+B6W4bT$}#(s(5;Hujwn zDrl)DH52qFk_7piacW+}vWK`BlZ=n~z~e3PepI`-_{M0!Y|5Yc5vS0HJQb3DSu>WL zBvY^av9SSlf=?&^RndFgy7h9GHrenH|CLSm+7s>WI%0iC{Tmku|IZ1G#@b-ynbP@t zs}+AJQ<#%WR)c~1WGDc-TRPLn z0K1-6(zqyyog$I~f#sc585tje*csh;sGwyb6*>wY_6=8c<7f9Mrg1tB1{UU>fP!GE z$6+8wSutW7l*$Ybs}5#>e~(qC(-i%lv$2;)yvv0cv8;L3R6w+~E%yo@qNpUGmf|`q z@19|{MXd3N!{<}=aDeIGtF^ItKFz`0NB5Z44g5E7GM~Fxg@e73)4QXqE)HT`p0NVC zzUo{(iH$-y97>qn%$T@`^4DtOlpTh7p(z!FI@;hhKN#H_BgXOB+D_FW1!HfIo`vdK7{rq_pis*+m zr$cZAr#|inDNGbxPsmLVtrktR+9?Rs;%`cH!9^K(%%XhPqJi9y5galfQW_{Arhjoj zbc_Cl8%Ub{fRe&Sab02%nX}H$Nz}i(RG9p-qrz#OvX9ase%U<_J725wG ze6)-9e-e$*z_-WP|GE|KxXnz2Xwr(o7oU3?;-a1F7@Pt{A(bi~1hKoXR`J-gK|MJXnK(EwGL_8}egiB2s ziXLcbU?x=d#!W1&`ger*z^C5q%bYKDvf+AbPX9!WZ{|))nO&%gUT19(!l(v~E+Rqh zswC6Nzg^PcR4^7C?+2OV{$8bZ9uUSw>pl@f4$)Npls_iQnEeBBcm|v~vuauT^^&1b zBLQBFQGcZrxrZd3VS%HOlgR(OG$*fSagQQ$M=}IwwfJn3;$r;qBN-91!cp1qk7y+D zdsuxOyTWS={3f**7C7Y^M+KoLc>9o3%@JDO3s5f3I|8qfhT*SZtW-y}aTR+V61zkT zYPj@*1G+$lZfY7~rEP3?s!fg3Td;NW(P#2#dm5@5yD!%KuD48LD-!fH0I=vm4E{~j z&t-uTlC718fw+km6kH0atKatWM1&RJxJ=_JcXBSORB$S8IwbS$5xI6XcIaR}C>Ve` zO=xANZ}|VeWQ(5j|3(2xN}AlgBg@K490J5*Z*sNG4Uns!ep3W#YnU5HZ-nk zLr8j=7{K&kXumqP8zvfsCE7(>#!Sa4m*MnYF+!(#T0XF*bxRnz+oxZj{!=EBusgFH zrnH!a*8<)x_|y;>8Kj)9mji+5}fuJ%X2aU!o9uWF zK1phe?a0Kqaj79t;O-pC;+6Bi5oW$|!Raept)sRg{IY_F6M}EfZZR{|(aL_!_rC`R=h(>hYWMw8M`E65CJHr7x+{ zg;uH9z?B{MFgt&w<4Dt3iU!~#OkDAYch8&1$H!q0?Iv_KB2eWhqtUO!TISZfU`zh)6x=kjsypbNqCeYYcA#@&0TS&G7@)|<8^CX@ZP(1NR&vXGH zF8q+mmFWbib@KDo!aqxUwaL^!j2ylU{@A+jm7MxONg!!15_^B@@WxAMJq`)vri|RC z!JnmJR%d1fvBpS8Uzjwa+eK1#AO>Z`3QqEV^2wjFOsKr{O#3E!HeECW)(z6=&LLaf9X-baVPOU@lI&%haj@whMRyJe;C|xA-~0!B}~=&vqw*>08r-2Xb<3RRDBi1=}F{twQ6Mzq|MR8B;cmW zup0)#(ODT`-^`N$;5(owxKB-y3wph)8dUrx!pKWigMg|75JXL5vU7(OQ1=0GMpG;~8Q=*ZJR3;dIY6bZ+K-L0 z8t8Nfa*<Apob;i;$|;_%|b6k&DO#{D!@+gqNn4g`Zgj0ZU%?JxPdMJRNqs!t?v@nI4z{d z_N@9~YgWm0;5jy=pzbGNO{tR_#sJ9R2gNF&yB0 zBU=o`d;ZBlOqE_3pw`F7*z3y3j^~>~x&@Y~S1pk+@hzmPk@Qu96K!k}#18tMy^NZD zG>q58q5!_O7j{4^UGl?<)w-fxl5W<=Wl)DF^BHRWQC||h^viSNipwS1lxM|JNRHMb z*8ix%Keqe=8DYaO5^B^^qkU2n*2C|Q9Xb_uI|NnjCq1cWmr`kThLJrvF8E zp7e-+c*tOhS!l2?AxG^K%M@$6$`m}Uxl=$Dca--MT|s{Bk@0rwB)LYBr(1AMt<&&&h(aL7kGp?8RCla&hNg1Ez#WIEoa zyyQ?9f*}ZHR#f%==U&t2gj}e`GOpq$7e_Cicdb?2fk8YuT zOPCG3Yt#1D;S1zx-n>l5Ivcn+qBjcrf`E9eO(OxoN=Kfn$Zo$0Kn1#*G)V{=vP^(^23AI-CTI6K;kr23X0!SP<9P>k+q;0Z z{2TXketKEQX-8$fhcmb`MPjO^CNNR;E><}US zA`1Hcz-q;tHjhH6%rHyRMgDhsm-){Fy06A}dOe!M1>CGN@k}EnBO1A5OKTHAD0B5eysRuByKSU6}sq zs##@dyFh}oSrTdPulz)p4&{0ilBw(Y(L{qTxEZaAt8G_O0^r|lpo42~phA$Dvf;^+ z<}YD+&!9jRPOFh9P5{H^Td=<`BG!G|OEmDW zh*NI>5~RU1DD%s*e21s8;#v1#H3*^JHUy=Geqshc-S7XyY$fyH6BaI&G4}6uej?oQYn$wn%Oaf$DI?;3^hnC>dS7PX#Ub=hE zkbtz1v-z2VgBHf&Qdx$KC&mk6ewt1h?RhhrOSBk?#&E3tH+?rac84q)wDv-SAXbFb z{KJA!A}tG;?(OrYg$@s{eUl4@o91<5058z!jo(R<%xHt z#s7fztNK$E{?j%UOf0h%wQWA`raslV+ugz#NI041khZgtH{x47;2W*_c@j)zFaE*X)gAA)6|6=q2Ckn-KtChE;sUcG{=;yqGO6!~A)|O4wyuE^3u*xdX3iIQn9#@uKi6 zZKKtvq~kS^SiYGY(4NzlSBK+uB{?Z-OmC~?=S~MmD)#rPyAP&0RxT^~qWi9&HFs;G z{*YLrb(@z>UvpO)BSDBUh^PZEr9G9mz}ml#o_>kbOmKRr73MOt9@yD^a%Ouo(qQ+k z_7w#EXfiX$L3jc5r1DoQW5^A@2$Q%Q zDPrf9Xd(F`4+7P(>fIUWyPH^v$oH_6;sXolLK3oYL;doicCuol;Lo$}-yn~`5%yp@xG}~01pdavqF^H(L!=X z+fN|OaolRLOHE!J+QV;PyGkhVFJt92f z@UoZ=v7S!~$nyQS-!>HYWa#Md^N5Y}P>~COzZHD!^)k+4_#zreeM7CI%4kZtc|lK^ zeuU!ZE$XKCXSz0kQoP(SC}SsCKHu2PSs81L5!ZNSwT_U}cBm!iqPn z93{%WDK}~!sGV>0h?%F&&1Y9py72llbx+ zk$XJ)<4EO0oX5nVA=Zo;+ygBOuhzS*qW<#Vu z6AZ)ozypd|@?DNVvpXkT$Z+PND!NPK!Al(qvHiE)l}ccq)E2DA!W#;F_Q*U?gNk%# zZW70)u7^k;bh^)_cWPYGV1|TsriGWSzIr>GKJA(;ZHGU0D>RYXIh=C!;&%V}rU*)%X#Fd>iRN0#JEwcoiQk@6Z(UGAng zk~6wizgg8o%;_F!(7^bRaFD|q%R((ley`~RFJNflfGh^rod39gjf&K%eY+WTas0dE ztqPi1HohnuLG_!;UPAf74(_-%9|EHjT3i=Ehetiv+<~A;mhnLp zW;ageQyfE2_HT8-SQPq989+g@xazB1)-=mj1sCT16FmoqMFnc3=1rETG zhJbfJ0RD;@n{6M9?z4a#iY<8lBC2o-^vF|XH1ktWLgAwOF}V8OlqE)wrs=XAyEB$N zd2(06{8ZO%Zh|>v=(y!DcQizaynu*xV=!4$t0=sXFnR*hX-M|C=UFavZdBwGQ=54G ztD=kGU!{4^edL_!iG$Ndg>U3$AnzcGLC^;5;o?_kW_?!BgK8)PIZDI61o)DsWPev5 zBPBXM|{|E`N4BHtx(uCTXkOHVxDAb9F-)UL?dOkG`t9%K_Pn1HAs$HuICGkAC_8)eI z!kIOGLBl6Bp?*q?RGXPyhx5QU*G;a{)w%=uRB~I8-+zbI9m%4&hhl)>Y2PfJ_E?SW z>E!C%Di!l|%F1aDFW-*?@<#!V;=fAUtKl5Nlgv6{riAjjLl4AXD1@yg1_Rk3@oWQn zR;mekq1cj&vJuPjcnnS@iv-E3pj)#RO})A(Q8z80$AhF>Y&*R+tE$Y>W3a{XcYNUL zUgV>aGWz*qm_fbmn>#)do#8yZTKBa_Y%1|zgXwRLpz(^a>>(V%q56aJa`B%`3_*56 zdaPQx?L`tm=oYnKu1u{`Q$p!`AZ{3t6R$YQJdX+}_hrt}vC9{- z&6ltO#7w2p;O2(ZdCK2=M!k5Bk4bOKHH0;3C8I8L&VmR+V=_c@+_`mz^x={* zj(zY^$7gk4DOwZFm+c7MQfykNXpcp~h+HHEj(aJB+_mEKeE+Zw=;#>qS}i6s{p}?Z z3bU}R%g5Reg&w*U6h>NWW{l*Apc6Sk_)RoG0iesz(^h{QZHKk{=`udycDNyjYHSkm zOyt}u6!97WlLX^n#SJSfS{C_7#PS@I{<772tj6&?3H(!eOr>v`JVn!9@`o6K^g*d; zkd;ze+HHuLT-o0pPC_n9Ik}~*7{Xi>uKmvc9Gg~6cEq^0;(d3B>x_}4>)2KKJ(qEmO6t()LCyE+^b|=$l}J zSHAmJuz=Hr~sW zUC5$kdZ3A4&HQ|DQ2f^bm5@?@G{h?V@J`4FirB=MJp*Wu$>L8FIFvN!Chw>ZK};Z3 z%o^G-s!Ju)$HWw*6?IZor|b7?IcK)bS{@+tcB(%}G1oklol!$Umq+uDx@#a5-bc#@ zLw9l6VY#d+Wol}TnjHPf)e!tIFPHT_J*{&&^|J@kPW0roDq72*SN$P!Q$#b1lSLQ- zP=!)v4SxgMf(d4X7;AA<~)s3fmB*~IIXo8JZ_;Tvz_cgWpt zgCs=1<@r`jJZ6_0X%RkNQSKoAJKlULHm26?)~$Ib(Y41pplO>YAKCWv+lPvbKEJ=6 zCIe@Km6cLst20rerUYB%`UEKBcyaryMZ;$Ru=-tQLE9lZ%{#OpkEC*on1&8bYFO`vNh1n1k}G1?zXt_&1kqUy z!V!ETVv(@D+y82H{?0{Tx@^okUTLm6+p7qJ-d)aYpUq)5k=}hhCY{A zVI`+(ua}f7()ImR_<-PY2btm-cT?@%%a5g2A+I>*YHuYas=^C#s=^4)Rhxr>_>I6$ z-r!hFJ$V^O_Yoa3HXzcP7ejlrx3n4s`pzQBzyiXQJ#iC`o+WPnT-=Umvt14mnD7aC zlV5z`ha4@J&aeu{#B3Nw1*GTD8}ws!)s1lkWHZ?I zs#%f{uVMPB0Bto!?!l00{olGA{U3jIx_qBe!Hseg46)&eW-NN}s=`<^=IZlgc2>sr z4ln=u8K^Tc;hWHj2x(aiQ2A>6o4)Dt8&BDdqx+kud2K-Lsi`*BE=Qp-Cm}&7m9|A@xqZZX5U0B`t#O8mupTKYWHS z(o4k;J%Ik3kN7y5X}2~a%HlHl;#woAKQ=$$mosWm>RX0j15E5uEdj3Ic~lFST``9=gARu_KzH_Bk?T5?<)h@uWw^>vB%Cb5iu|2D#$W& zvaHr0Z@g$PM-)0yXl95c926#y?Eg@&Dbf@@3LJS>bj=L@@#-UyP1k#yhrAGt2zsVeA#oGM5ie?YWBYM<3dI*dK^=PHzttByE?pPet|>3w53g#?XAFUQl@n!ymCu>MHOf*By*tyz6<_sp zE_g}*8Gr5NNnMWax4(C9heTCTPOr!Ejyu%Qb3wffhM3&HQxDrN)`q^jFMU|axjpnEm9fX7qeRCNm&EQ~Luti|xqV4f8f_VWp#h-0EK#D2E8J)U z*T(eR{02E_^{ zHrSxa@qX5?;`AZtO9zzaJ+6`522-B|l2`j1m&)F!kp!g=9S~)~wYGmmbRXTnw3;HF zstN9(Cl=a{sFV@ih%emF0N1$v4aBm7!O04mSD&BL7+^eO6Uq-dE_-|P;)Wk(_OK>8 zSU%YwCtW9=?b(f)HR?VHvMPjg)KtS|dVD2DoEp%kT_;la0M>L>FYK?kR(`$}u47nG zzZomrJg2DfAabVuw~Jd}b{Iwea$pR4GVQxGU+X}(UY1tKnqkG-2}^v}aUJS!V7F9Z zy4~e-JD9kxNf0c^7IC;aqY=INO^DSx8pLg?)ocGZddx+}N#wkcdb`!%uXMZ9WTDEs zFpX#r3bGdhk)c0!Tvu)%Cy_2%V4hY_idI{eKh@fmOSRU@>D$o!H>W@v-aAK`%OXH3 zM8iEboV>Dr2+RSh$6TFh-?iJM2@y_-+nlUiiE9v?{Sn;UqMqkYcABqRgyZTJYVU=> zWW4C|U?Vw_DlP`RN_q$9?*qzNtOESCBaJH0P`k#B3%1v*8c@QUY{!f5?iHz??)@@v zP0{aMC=AnMUtuQP?2J!ehzj_Hq^ERfe&by%oBqZCVBKle^OQ>w}#L?nAEcJ7u1{D9`TJ5w(jq-)^LaptJKLmt+(w-*_=R^}iI5 zg6F6PjmXeq9`q+cSc*hiB&poKS*Fn{%iP+~$6R|hd$rxoye$#ygi-bOW!kOpYlk_4 z#7@?`$m7!OxHOARfNxGXAhx4Ny5acy+j^0jqR|fGw{M!a(B^J8N;vo=CixDc-Y=%B z_@zGkt2Uj##Tsbr{%zB3-l}r4Y4eTdiThn{*^z_icj*Xj;j|1jz=QW#mk86Q6@Ax5 z0sOYGU0n3sEr+DHZW4RDTWd>Mmccoqb`Om@v$5BVkiNkAil75bGccN9#qrXexLR(2 z->c)Hqj=~(0D^{(l}4WaSy0@}(#1g_Q1$*(ntxA-=UCYEKeh_RFS)X01$am|n3t}) zSSAla)0rjiotWO7`Bi3n{rw|Z!Z}P;q(<=6H?h($emG;Ra5Fns!KXfB?QGF|+A`^- z(q$j-*m3#ZtKC*+1uk9-K~yDAQT|Ux)F|A|Tu$PR4P46|O1@E0qo|*px~In*0QmgVU%2D!9w-?w{*RlobbHzV zawS6mni}tAA;>MOOia9hSNm~O?Dje7k=Hu;D}PuRa2ge2vfd?;6Shg+eglnF9FJU%isjv=LJCeRAJcqAF*m^7mLs z7@?Ii8UlZFw{G#VP0tE{WAm?#Hdrm1dgK)po$;}8F^Mtu?Vd6~9R4ic3Gg>scB}Fbe!m6y#!c9y6e)$2+8vVFTX%JPqu6ja!|+US z{8DRsKmy4NK+n|O6(U9N3hSQ&p}SBt*iY>W>??nz@2}=_?!LKtW;dMq%60>{n#p^D zxYmA^xYqHfY`WwQ4ei}GN|E(J2hBbr-5~3lvAs!%Wh-`9iKh6y_6vWi=e!d9g4M$; z_MQB*eoYJ5nY%Q#>SkS4gZodfmN{t;bGAjUe?djA+e-g^FV}kSrya@319|@efH)S6 zhC?l^W=zcO$qHO)NYAAjaXEH#1y2^iq|1)+=`-WcT^h|76AW(H3!kkhbpL%qf|Ak+;T_D!%I`Qv{+WkJ{9Zi@#dvdxVw`)|!wfpS` zk&eFrk^?-}AVzNLbVMtFkuVxi!iSBm1b76b-AtA=2n z%p|+7y=ggK&Qvgb#cvTLp^`DfC%XC!I3hCXJwV2=(4Vgm^MW{Zk5Wjfvb`5J{fI_F zv9ja(3BF5nTHSldYmyJmzhOuK<1!{N>x!4ya)M)%jjj8H&&O`-RZglqIR5KG6wIK` zl2LNZ#9p#C!Xn+ar;NkM)HXhX)gqk)*XF(NLVI`oviYVD_2tu0Gx{hWh&N;HWKc6_ zB$FEF{sGABE47_s{@dTwf*W1FEJtFw_RT+G=fo`tMgt&IG!Y((a~g!_D@9 zKlY>O(eY697##-3R;?z^F-D8ZAtujlXS7e&JLFVZh7DEo%r_`Bw8he}e;`TWU!M08 z>EL^X=$Rj04O?d!;HDoO1Ih7~7fD_*<#Q1KPDfMuGn@}a<7v)U9dzV1@2COtq>`K# znw%V7hlJMYkkNmPequ>?@%&R}P#lX1BrZ%;myCB{W?4>vhMQ~M<;lPMfZD^3FM@}a zt^e}5c{gw4J~6R^U-t*Q69$v>9tr(d<-evStE`?;!!7%Thx74eJzl4@RTaYR)^;M@ zQdfLD;6ve-g<{NMVOM%X$tUqT4v;pL;D7U}PW9=(L%M{}slh;-l$=bpJ@&uD-@a;i zdrP<B{Y|qLpub7-Kv?OGx_;Cjo(2-#Z#0_?J8kpIh!Xe7Nd0LvVMh=^w6qyV zNH2}LAYDr8BiY!&@YisnK);N0laOB})TIB~g7Gy-?U#=w;8gxM;GZ%0<-F5iSe_do zdfJ6C^lT!w9Odxno+z{7Kv`1<8`((8bQw+#AXa3%kar>-m#-A zz5?8?is1fvyhqm*Rg8Y2{xopYE%Pfp@=8^U@N_1#`!afeq28bS z&KRdCKRo{XYG}jZ)^=yncY}s!bl>{V;~(65)v0g1mpbMsFK%i@$LnJppcOC1_3v)x z9A5>Q?zJ86@LH3VbMfVsLgJP&TfaVSs+ zYd!RFy1MX%VHkQeL&2mFsX$;id+KCeJ_TnAc)43rrQ+9@JSbv6_ddO|`{CmdBTZTY zK`9Ld6R-Ive+I8670lq zjUsRK;n4#*mq-L3NT))T9c&O~v<0C)eUWFJ4j?J&3#-(bOne2zT*i}BUIeD=-{J(p z>;7vPnagzVp6TtIeZ#&gqkZV*n|*_S9~Y#KsSE`Fa2tr<+WGsXBd?F1d}BO(7ISs! z3_zjm{!Rk%3T>);tL7lE4TIJX(eI^<4x202cO+TCi|J+Ag>%z%SMOLXdfl<-9Oi-E zkNER>udY=ZG8+&dq$(pTq>95T8gpa#+qMXwKL3=;-<)aNIqfuc7iBGRXP-}8@mgNr z_?L>lsc6cM_mYBA;jGS5jZERNK!)n9v2aF3v!#@=`wC(6d8SsWeh)FwBw!=x_CXmB zYD2CmR1KP|_OkJ~ZCWo=P4xGnxZUFD0mqyqs>O@noG%)rsg0aR&>QmU31!T(S-8Vz zDj>EqGAzPjC+|8l%6bI$)3-U0fx&ws$Oo3iFP#P`{#_>l-zfc_^{_6hJh}JFaACv`7lwi|sd$Un zU8tTn5+Aoj+T?3i#_XqSxpYD2XJ=yp(L#>>@uRbInm=9vg@wYhR#^<^mh6WhmS~di zxi(B<6ybcd%pP;946~9hwoF++inA*b9|73}F2Z&TiW(VpK^~(snQpQV4eEvW$;PHvpw$Je%jdW* z<>Ka5HQ|lMD-+^*$HFwA*MONhZIu+fv`GvXGNQ$mXLdvZ>_Djq4LSD9Q~TV#eWvKBm9{f- zO60^qZYtRxY)7Cpc^WNCgo9dT<6}Q#x&=*IL`Io3A^@*@?e_^nr7LJt?lMUD{US*C zd{W|;zA6mgDO{zrz4b|HRrg70f7?QRm*K(Z8;#wuG7$fxiq~s@m|BdZ4we}2FX2*N zPoMhlfZ4#m(*o7d!9ei}QE)xs{1!ytcjx2~TNZnFxIF7Q*H}|jn*seB^R~!SHvsZJ zwhr{GRKMvgQ$|XvslG9AqcD7w=Ysc_+o)diNv5BhMF*SP{=A}o&Re&Oi-_&SW5ewu zbvS=>0b;bH5y9VrjDyxzH2S_W_7xP`akCXR+n3)X!Zzk45b&SVix$fR9W2+#9;)Sb9o zee&YR08>4@^Y$I&E);*GoZ$0#h12f0Df$^f^BZ!L;x7>@B9kk9H~;=wkZM<^6Culs zq484Wv`5{-df#+DZ}QC^zm68w)3h!lk$?EOd(Cuo2P$V8(0$j({7&;~8|lDr(_|iG zzT(Lc*Z;V@&HJhDmpoGn60E#CvO0a@K~4X&PC-V2NmO$vQBCuBwv)rRHBV+xHqbl< zk%Ey25a;7Y;S5M+6~*@CALHSk+1YX1N}Gi#-!1T*QLtRxX2|olwMtr<908C|j_T?7 z*ON@oD5^`rm1~#8={#@ly?erv&?7#13SIAUZY47chtDr|zf>xnpk>Pjy{>YVp^ zlDc>{?muD;yXsR@Wk^f>#qjtcSVj9<~ z?nEsC$dN9B)tN0rW(t(ldsSgL6KjVkKh2H?GmxxcNexZGf?EuR!|x|~ePId^^kM-3 z$wiJ!e(a40h3fVgBpTQGNCCjAfI-RH&xeNL($R|r#>b|`<-(7~%P?Bc!C(9mkzc$L ze}C}|?hE)|JiS#|l0bV zlq+h1DFdsiDy{k;*MNDCx{I*dX>B{~s=D@1d-0L|`tA!C z*gI2p^V6I2kfJ9kD!}^Zr2<9PBgw^qs~A-4eB%jW%x3pT_lkzVPk;T|xKUqXydYYJ zjYa7e76&dz+5xY$IeGC~PMl3}eoa=36>s^rjsDkVHth|fP|7B+{ZC}V!m}!e-ysww zEH~3i9vPP2k+~S^eX>R)i-qosW6IR4?td7$Uyif7T)iT7!XD6TDKLf8l6U-(EHSip zMc6<%aD=0;S^%$vuDs2r$(qoQd_l^{@06AiO8i#mO-S(dhmdA0mnrK>*TG}nX~hXK zheoXu$T}w&)cP0jPI7pJZQ4?>8wqD)KJS|B?KFjeZv_4nCCydps)&F`bbiDJv*j#I zzYqQ`!x;KNJZ`^ffqt1_^|Mfg~`#8w)WAX9`JLE+v=Yx$~Q23?efIksDK7Et(@g0_N%B^;;N> zFyite3#U5G4$A(Aey6EUX{X7R;Ogna8%b-TI)`78_1^pIAxT}rDvB~cL1Sc9t2f_;$d$uzb$i_K zt*FFyt@TA$ZPIvKQ5u&1!25YpgF(~Tt9VBEc#?S$G3QpTVzpzgUDc92zkXLNhwu@5 zS=omeY`)|-o!a(H5x2JQ^myUil#oAmZgkmf7%eQ|`UQL9U5h9st?=OI8fIC-yc$aZ zBIko5k2xX3>TE+JdGwr~3!vkz5scC-i`R0arboOC7#N}Fc-Hn zcFRJe4K?+jj;Jk_SE_iHD!Be3o=Hj>a>lHndsj+6HtA&i?X8q(h*l5~PPzTXv7NTn z5W7j}6DqO0^7@nuPn~MsLc@Wa?^(a7R;8sLmiZ)|?x3l`# zs6`KKvGp_cV^sQ%*irjXke4XYA?C`x>%s^pe!<Dx-m z+n1HE&)%}%+>oS;?31J)&r0%aoPc2!j#~lu_{lFp8LOEvx8jh~s=J3)^=y~qmo)G8 z6kK#Fc1uN%oZynHv^$M;DM*oK=a+-B$~VZ?C$f zqHAFnR^x5oF%QbLTDNu!XO1f9HL3OoFj%;Dx!mRl1lCMVA1f8`XTb|WWpDc5C@g!bkUn8*5^R(rPS>(y%KFDyWAM82a8cWia*Z<|x` zujN-QcJ@m(*@ph8=eq{fIjHr}v-`tbi3#DsBcYg0j?7`$ukkAOd{-(qYgBvbOfz;{ zD{Xrz+MnFK9kjV=_iQXKvB~YV=9vJE2%?cZ7OgxeNQ$ z&FEJ#7*2rjy)e8@S~<7J;*He4hG!!th*Bqj2Q> zMqYo7`}B=33;`w4=!c96`Dj%Cz}{)}OF&)L%}rHyxKBHDWbDkX zK%f^;z9SDb%TwX^)gs=8dT4ZLow*;swj12-p-%=6K?5A%@R zGsi!Y_tj3hb=9_cXVn676o&p^(FRSS6`V=aW8b$<4yscB94&bh3H4G0VuDrfJSmTmaC2^f;Z zxLXHxI!6mm%d!sCYW_7DjV-GUq`^{6y>{w8)ig}CEWoXP%kSS-tFIB`zJo{f?bq#B z^S`dgG(Ds7S|RtnK(HeAKTwgG5T@`{$RgEPHCkcpsc%@Kti0$Yb}yWD?wdtM=P-uO zi_!Io%-cSJe-W-XPTf7hm0)ux@RP`;O%g%R;K?D5!{0a5M1EL>kY5a1#4HuPJ(|o# z1aS+2O7x1s-?jYsBAt{A1!P}yX}=u+7kxmSyfr;$OJi@(BRUTU5PSEz{y1q1flsH1 zhc$D`kS3r4*fh@f@BQ!AEMlfrJDZ9DvH-F(jk{)f z4Uf#a0~Pn*r1yMnbp9DWIe9ABacA)d21v$@jM$0v$#>%Vkc%!?v>0*it-@{8{d z)pReW0mb-6N4@z52G7+1w)K=Y(Ue_`p+Zo0bKGuVF+wWSl!+yFsP@G$ENSCTAQv{| z2c;^VK8TmTI_SQNUC0a+Ikoxi?-xy49_si@R10ZZI1hVb@AMU0U_RMxb6)IZk8-B2 z=8b{=3D)vdO{`=2s=WWftc*X(?VDq%Q=#4~U07rEq=Oa7@}Jvx%U|5V%U=xffWbU{ z>()PBIPxZ2!{%76?5$5`Ri`7L!Ixg!*5jgO_#rRkllJReylUIrC-XehUh|Cz=Y~&W zGt12}So*%-INDr<47^bunxOV*%$&fZl%pjaa+{$ZODGGX4!+g! z%vP;kO9}s-+(X7HNB;9YF)N1dOwZ;u)NHc%JpU`tlQv;2`{|!jrbt?&SK_Czz?ykb zA8uFdw`)(KW`5)vMfUq!V~M=GulhrX!IU3n>*`-2NjaF{z$O5QKJ1g@`pn7d>RJvW zH9DATYlkOmE5#*F-8*}Q#P*2?SPK8y6ZQE4)Lg#b6N&?Wul*&gRq(Hm{*p%j@3QAh zeEtkDsz6T+JlX?qgEcR9kc{}>(g8N4Gp4S~b+qbvYr`kl5doczI)uNv< zW?v!DK_qFK{cMH?TsxPCqJj)s!o+9Bu>K$`NoFo4|E>AyQL1vV4`GoIddxIeSKi;| zw@TCeQNErxO^)6!73$Kk@;pVfFK||Y|6)O2`$AWFKCA0{Ro54W3$a@-Hll}w@iO1+ zsxC`RL|LJ zZp7MuAPnIMY`ppR_n}Hll;8TVvNRD)iAC>4u2YQ!ei4Pigv)}gX`f6eDACl%B(ub^ zbu&XhLP`1v8J^JxzATjCHO}Qq<+>9Ic;oPMDKru@`0-c2myJwq(f0vOV@3k1>t~VB zdbx!@it_y${pZBI3&gzXUnB+GU5Wl4?9+hN`D9fq1S1q{quKp5;Qu2wubVXWaz0(g z5FL0+A|x+-OxZw2qi;~_s)Ufrs}n%><6f0W%YVbIEgZQgM#Nt^Mkc*czqXIa2e`U_ zib~$TlujwyG}4$ptuArfOqpp!1NDqQDE&D`h@ft4S>Q4O@9$>~ z_|tlbR6!88vU2RL#_tQHvlv8%7xIoTwTwq-LC?YxS0l+wz3(c}J`H20Us6mKnE-jn z;EF$C8{588OCLC*Fzvn4B*`fyE}z4&#P&!W(k#VOsvdq{q<%5Owo7N3rQ{{Wgg1bQ zXWpcVA9KMYCk{W&f8k7f&{Oa6T%$H@?YG9aA;!o_;MfS6`k`IWIXoemQM-e{kKU$H za}9R4tG<{6(I3wa2uoD1ko&>Z^O-@mi=2=|K55;T?fpyqkm3s_$>4c&ZmpJ<7MUD< zQ-GgxYK|AruHxdDzx0)3tlY0)ZdMHF%MN^z44vn)gVk&K$|#SB0wclD%kf}Xhmw$$ zuxgv7uxwkAn6gljsN=WYpFgauC%(V2o=+UG8TpNEa}nl0HAQ<=&@c9oVCjFxnSMHZ z4;&Z?hkqw;gnj5Ai~;}*_QY(T8T6}CXLbOru!GuHZ0Cwwl!{1Xs~RWG>j}1!d_Mtx z^{#XOsTQ59$(sdLq(w08)CIZOPIBu4+^#zKJf)5TnMpBTQ10z34sG$zHSWgLG+0RK zf(JoFeRq0Rh^D`G(oRcLj24b?EIBmlG+&!0mnrI^xIpERRRZD^%g$fNyBvuKnk{J! zyrdZoTo*{os;?;`B{<6n5-GdSfbwTRVOde4#ZwT;-_E(v?hFQ!10=qaICJM>X^0Q6>?2h3-Kl;@ti1dA8=}LcbI z5C|mioi7#^!kEJ4Oe&N7qC(lVs7Szi(a-dL*q6E>3oVx4+Uki#1lzu(*12Wu@*DUv z5`V$W%lY^X_|B(XPWU8j?m`!N&oCLafNLz@rQ)43MW)fEKt^`{uS+dbkrIcq~j4R93E#~4vCYZ0eKhmlX7ggZCH6fv6iW4Ka+G_5{C zk=dnH?-J1D=lLTMN4a3v)go~1N^#^=cCM?>T_n2jJ_^14M`9ZUyswcdYXe2= z4K}R`hP^s<*=Hk}V+w@k{fi?OWUOnA%xYhY&Oaq4v0oQW*WC%+3MU-@^ajK z-P~QpADR7;VskaR4bYb|j^7=mpT0cEIAJ=-LccutagO6~vni^}ea8VR??Uz*9pcK2mg?>`2R0PzCz)nQmI7!pzmLp~mfkZ7accNFN?*67ZlD6>nmlF?qI32kuk2 z;~W885#_%_Yr&1mI+Z@J9?nKpZvszlKj)-H05&Qx(En3cyHJV8c;*cF(fhC~`F5bX z*3-FKF5htTw|OG=MGuYe^_-gIasqsanQUj#&JQ@{vNK26=8ja^7vcd=?tRt&zBB-B zI!U`a*LC71kxgOTs%6+J_oLVsBTL*Ga0&uagOj@b611JMjm7tD0>`2IE98@$?RR~I z)Jx%^DVM^}$`?Z~a*XF?d)52Y&6q-~9cb*STPYF&@*2)U&N#4%>NYQnxE7WCwmG~u z1f7_&PtM23tu=-k+t$#H?FR%C$c_Pf111oY*s-FlKy(EG-s}@@_MJCc>J)Kcy^7Iu z!?!-Y+AiIpC@~+ZqVX49@=Lg=m*|<|UJ7*XVc1 zMn$gV`nqCGX8|Yg3E2e)WHh;%3ADVX4IYc@^%?!P86@RGHbYHK(|6U5#i;E2V3sdv zB2f90^Ify~PrfJFrhRM+z7^)f6V--IZn^!#?Aiwu;5u5(8lel0iGq;4!x{eSHwLMG zw98O5x5%f~I2zUkMWPgkJnUiZ>E*(aovK=|^OOiyxLLnktMK*nOrtxTSqe>!pftyz zZ|0v2=whg@AHy$Mhs=fqBhlHsu^gS&_y&GAf}o0J_)y`k_0P@Foj>InsP?_^@iwf9 zSASGf3_8Bs?qO-@*cg>@^xm5Y;T+cO^OUg)^^Ry^;+4L6G^^Zxg5ZyoIx@8f;Yx&O zS#k$revA*E$N6w|+@~nj$0*46d_xzPgjO&0pM2uXLbE9*NxAM_8JP|^vxUo3Bk&Zj zM|U5p6|zlq`A*%U=t_`DE0yh>OB=~xG3|%w(IR9}Q)k&WTps#PKFI}At*U>!P`l9+ z9d0|Z&7j5CXbjL>Z@YTsf%0h>)>HZc7>*;Sr3XL{nwm#4AgRiwHa0f;!jjGpGMj*2 z@y=Ae$R#L*)UTcG*^K);<*?GO$gPXrfjb`7ym&T{<(_np zjFB_6u-JBjkBDsYZ)F`o1<)SoLw4`GkR7@+?A=!7ey z!RO8>Qg2923eBjnRLl#WsonsYR?f+fSBX4G5ojCgu=V16K5H6s0Kb_fE6F>hVPh}NE#m@(#`Bb|-$sDI!oOHzc0HYs`bm*^L>86-KN+2DbxOWM zh?_7Kf3Ev7h=0o4l*Uu%+ObbN9AJriw{QUs;0dBG4o}BDCn;w;EUywy!NkQ|Kp0>u zlB|M@uzD%MVsxqi-blCVk13{bOMHX&+7-Rl$z~s*L;4>p*1k*4w6EFJzCg8aL>HWB zc2C~NMpH{TLe%8^TG5%PizE{u#qlVJ-%T?7eF08vL#u>*5|btS!)dNyRm{cBoo~4Q z1Tj1@!G8pe?G!0J?HdLaTt?3RvYDwjA#JdKDa*b$@M(H6yTt22&eniG5OYt~R_C68 zxBB`!A;$yJLG~loLDmh!!4Gsj(Cv;1-d+1XfFiE5n(D1L=`*PRmyuy}D62jB{ZU_r zY_%ouSG%uB$Hh;9^WC5nwd}QQAP%nX%7$61Vs@RxT-;|~V~-3UOdQv=k*a`ql+!lJ zNt>ZZ_GS8)&j2{pzsweyik?^BLIBKfVPavgJ@K&mf5@^AQB-W>Id!-b1(CJr>D9Wf zyn#CYDGf^OowWVlb89U|5#7mQQ@3vql*Wj%-?CS;j=4g^R@2ac`4Uw>5nk~!Pw|0s z0|&Zn?^D{YtXVkfPKhCAcmFGG)~>vc8ZvkXD|t? zi>cyYvqCZ--9iN{uW7G%4XN;@|bV z*fJ@~iXXACmdzm$M9fbQp@5HezA!T??`Za~Ooe1JYW?IKul_UhzN-V)Km6;FR5wdS z3PIX(OopZ1Vmwblk@6C*!=QgMMf8)Gi@UB=mMDze9G4-77*m4xh(5h{ne(z zbp)t7kiSn1qV4tMWE&@n8!PKd97cFlYxtB48kN__@-CCzQfcn8sICGqLvXEQA6XzuIRaWjZHQLOMO45OmgsV66&$ z^`>~BO|pE*zOwuIgBw3JuntoeFHSD5yrRyg33l=sbL5k<8f9jtwygH{T_(+Fn!-dO zZC-#uI98VY`Rfg~gdLLPa%>>4@i!0TU2sht2^xWRKW)uD$7?M)r+@f9zGauBQT=a4 zGr@yz7L%hmau0ioeS17d4_%p?F|MO9f0?0@a!x68Z@Xe9?-f1#H0G21-+YLNfALf; z7Mn$Q*+;%IQuY2T?Zn=vnu7z<5E6+HqZ8vTQv2>tKi!1iZT(Q`80Jc|_oJm`F@x&G z|F49RX4Gr4JDtFg0((!7I%Rw?z5FBtVUnco2GMD^WJ8!E>xqK)$y3_;6`XOB*1%eC zubiJJ5vx`_OHq<01FH_vnQq1>kv(sE#~i8W`ThJGP`>{V1)hU~qODXSW}PAxwN#h@ znx%}?8^cWC?<|JG!_H2z%z!Md2*4f&z;cPY?0$#QJ+FEhwIcOm+ravkH18mC=iP?w z(reoV!64m6CBOiZQ0g}Q%y#9No44|njIv#4A%>z@k%8-KL1vv{u1K9xUPql#PRDNu ze39&Y@As|seN5AIS#?$M4Xyr1?v<9WES-Mz_jkL6=V-CLorYV^JkbELZ~bh8>g1y$ z3Cyfo&i3K8i1qj6FRMj${)I!SAA7m=K&ietHAQTZCM_Q?F(-z=gz8W~_KOipasCZa zX(Ee>+yIpF`BTN&vtpnkWrZ+p@#ZN{q8W3_9e8@DJ6Mf5cK*p3dwJDLz`*GKeI{9R z7COaHfdaa$d>=_$7}j4q9#k2Kx8uHFsV8tlSpw<&vXC!=<@ zmM6BJgTnad-Xo!<@HX7;Ci3AvwELJje6HRjCzYc>iUxbJ)2F6`N_PP>YTJA zLz(rJ=J=J)Vv3H3pZ#zxBx~Gv=q2j!_oR*x1x0mXohiEtQovPdr{oWKia;?_|3SB} z3LX~bk?dXoC2y?Q%I9?sMH^{{GZxbI4sCwL=gnj$Ch}uogElYp^cBhkR4zMwIVDy` zF;$3pG%Xzq5*72h+Fj01}CjoL#N z45*s3V5UKo5uIs@>!4gC<@w2{&8fRX6GTr@?kV_Z7KFSZY;zva%7)7^X{j+3Ovb+; z(yll+abMZClZw=YV}avf(vgYmx{kRK07IUXB%@maGp;;(4U}aTtd|;J=-RIkMp3;- z2bI;U(D$*DUVF(*`4|aY%Dx^Wp8E6O&HsQ74*IVx5uKWi4NR4sgeCFsY%*A{#>Mq4 z>Q2r`H*f>S_}RUk7Gc`pz#KV?YirhGyU>`L-UusnPov+li3OQaXUSZTTqvNYWVDQ83&2ri;rAT_` z_bee-F#^H-D6C8snVPJF˹!g4WNuX93OGj?+SSSEvu%qfVo{Zk#w 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%0Dh|e>Ucg9 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

D%M#z}#$`yz|O~bwA{)ZnaPo4Wt`Np?j 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 - + diff --git a/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml index e253faa0..4eca1726 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/PreInstallPage.xaml @@ -1,29 +1,43 @@  - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + If you ever need help or guidance with anything, be sure to check the + Wiki. + If you still need something, open an + issue + on GitHub, or join our + Discord server. + + - From d3e15376b7c0f7ea592bed6244fe80f5cd35d4ce Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 19:44:12 +0100 Subject: [PATCH 173/178] Add old splat sound for old character sounds mod --- Bloxstrap/Bloxstrap.csproj | 1 + Bloxstrap/Bootstrapper.cs | 1 + Bloxstrap/Resources/Mods/Sounds/OldGetUp.mp3 | Bin 0 -> 6149 bytes 3 files changed, 2 insertions(+) create mode 100644 Bloxstrap/Resources/Mods/Sounds/OldGetUp.mp3 diff --git a/Bloxstrap/Bloxstrap.csproj b/Bloxstrap/Bloxstrap.csproj index 4248ade5..d7399537 100644 --- a/Bloxstrap/Bloxstrap.csproj +++ b/Bloxstrap/Bloxstrap.csproj @@ -30,6 +30,7 @@ + diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index e4ff6529..6824e312 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -1000,6 +1000,7 @@ private async Task ApplyModifications() { { @"content\sounds\action_footsteps_plastic.mp3", "Sounds.OldWalk.mp3" }, { @"content\sounds\action_jump.mp3", "Sounds.OldJump.mp3" }, + { @"content\sounds\action_get_up.mp3", "Sounds.OldGetUp.mp3" }, { @"content\sounds\action_falling.mp3", "Sounds.Empty.mp3" }, { @"content\sounds\action_jump_land.mp3", "Sounds.Empty.mp3" }, { @"content\sounds\action_swim.mp3", "Sounds.Empty.mp3" }, diff --git a/Bloxstrap/Resources/Mods/Sounds/OldGetUp.mp3 b/Bloxstrap/Resources/Mods/Sounds/OldGetUp.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..934a6344f26479e9e6514f78b5e388229125f71d GIT binary patch literal 6149 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 literal 0 HcmV?d00001 From d9e4251c2020d49d5c0f9f7152cabe5b7f00b748 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 19:52:26 +0100 Subject: [PATCH 174/178] Add credit for @nakoyasha almost forgot about that --- Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml index 1c082302..df04fad2 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/AboutPage.xaml @@ -96,6 +96,7 @@ + @@ -176,6 +177,11 @@ DaMlgNoodle + + + nakoyasha + + From 45d9f16f1096ab18ea4016d131ec505dce3dc4f7 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 19:58:24 +0100 Subject: [PATCH 175/178] Omit x64 from release filename --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12d38b62..eb38b99c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: - name: Upload Artifact uses: actions/upload-artifact@v3 with: - name: Bloxstrap (${{ matrix.configuration }}, x64) + name: Bloxstrap (${{ matrix.configuration }}) path: | .\Bloxstrap\bin\${{ matrix.configuration }}\net6.0-windows\win-x64\publish\* @@ -43,17 +43,17 @@ jobs: - name: Download x64 release artifact uses: actions/download-artifact@v3 with: - name: Bloxstrap (Release, x64) + name: Bloxstrap (Release) path: x64 - name: Rename binaries run: | - mv x64/Bloxstrap.exe Bloxstrap-${{ github.ref_name }}-x64.exe + mv x64/Bloxstrap.exe Bloxstrap-${{ github.ref_name }}.exe - name: Release uses: softprops/action-gh-release@v1 with: draft: true files: | - Bloxstrap-${{ github.ref_name }}-x64.exe + Bloxstrap-${{ github.ref_name }}.exe name: Bloxstrap ${{ github.ref_name }} From 145dcff382c3e0b9267cc9a845e722e8037f3cc5 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 20:19:10 +0100 Subject: [PATCH 176/178] Add info page on activity tracking --- .../UI/Elements/Menu/Pages/IntegrationsPage.xaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml b/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml index f0bcc466..3cda7658 100644 --- a/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml +++ b/Bloxstrap/UI/Elements/Menu/Pages/IntegrationsPage.xaml @@ -5,6 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" + xmlns:models="clr-namespace:Bloxstrap.UI.ViewModels" mc:Ignorable="d" d:DesignHeight="1080" d:DesignWidth="800" Title="IntegrationsPage" @@ -16,7 +17,18 @@ - + + + + + + + + + + + + From 7ab96a7aa61363a309a0e95af3694c03ca95323a Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 20:31:19 +0100 Subject: [PATCH 177/178] Replace Stars with Discord, redirect to latest .NET download --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8e361c1e..afbb1e5e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Downloads](https://img.shields.io/github/downloads/pizzaboxer/bloxstrap/latest/total)](https://github.com/pizzaboxer/bloxstrap/releases) [![Version](https://img.shields.io/github/v/release/pizzaboxer/bloxstrap?color=4d3dff)](https://github.com/pizzaboxer/bloxstrap/releases/latest) [![lol](https://img.shields.io/badge/mom%20made-pizza%20rolls-orange)](https://media.tenor.com/FIkSGbGycmAAAAAd/manly-roblox.gif) -[![Stars](https://img.shields.io/github/stars/pizzaboxer/bloxstrap?style=social)](https://github.com/pizzaboxer/bloxstrap/stargazers) +[![Discord](https://img.shields.io/discord/1099468797410283540?logo=discord&logoColor=white&label=discord&color=4d3dff)](https://discord.gg/nKjV3mGq6R) An open-source, feature-packed alternative bootstrapper for Roblox. @@ -22,7 +22,7 @@ Alternatively, you can install Bloxstrap via [Winget](https://winstall.app/apps/ > winget install bloxstrap ``` -You will also need the [.NET 6 Desktop Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-6.0.16-windows-x64-installer). If you don't already have it installed, you'll be prompted to install it anyway. Be sure to install Bloxstrap after you've installed this. +You will also need the [.NET 6 Desktop Runtime](https://aka.ms/dotnet-core-applaunch?missing_runtime=true&arch=x64&rid=win11-x64&apphost_version=6.0.16&gui=true). If you don't already have it installed, you'll be prompted to install it anyway. Be sure to install Bloxstrap after you've installed this. It's not unlikely that Windows Smartscreen will show a popup when you run Bloxstrap for the first time. This happens because it's an unknown program, not because it's actually detected as being malicious. To dismiss it, just click on "More info" and then "Run anyway". From a06c71b92c0bb7f244d9d7254e7a812723db2527 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 24 Jul 2023 20:36:16 +0100 Subject: [PATCH 178/178] Purple Purple --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index afbb1e5e..0a860a3d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Bloxstrap [![License](https://img.shields.io/github/license/pizzaboxer/bloxstrap)](https://github.com/pizzaboxer/bloxstrap/blob/main/LICENSE) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/pizzaboxer/bloxstrap/ci.yml?branch=main&label=builds)](https://github.com/pizzaboxer/bloxstrap/actions) -[![Downloads](https://img.shields.io/github/downloads/pizzaboxer/bloxstrap/latest/total)](https://github.com/pizzaboxer/bloxstrap/releases) -[![Version](https://img.shields.io/github/v/release/pizzaboxer/bloxstrap?color=4d3dff)](https://github.com/pizzaboxer/bloxstrap/releases/latest) -[![lol](https://img.shields.io/badge/mom%20made-pizza%20rolls-orange)](https://media.tenor.com/FIkSGbGycmAAAAAd/manly-roblox.gif) +[![Downloads](https://img.shields.io/github/downloads/pizzaboxer/bloxstrap/latest/total?color=981bfe)](https://github.com/pizzaboxer/bloxstrap/releases) +[![Version](https://img.shields.io/github/v/release/pizzaboxer/bloxstrap?color=7a39fb)](https://github.com/pizzaboxer/bloxstrap/releases/latest) [![Discord](https://img.shields.io/discord/1099468797410283540?logo=discord&logoColor=white&label=discord&color=4d3dff)](https://discord.gg/nKjV3mGq6R) +[![lol](https://img.shields.io/badge/mom%20made-pizza%20rolls-orange)](https://media.tenor.com/FIkSGbGycmAAAAAd/manly-roblox.gif) An open-source, feature-packed alternative bootstrapper for Roblox.