diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index dd86c42..d2b785a 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -47,7 +47,7 @@ namespace Bloxstrap public static readonly DeployManager DeployManager = new(); public static readonly JsonManager Settings = new(); public static readonly JsonManager State = new(); - public static readonly JsonManager> FastFlags = new(); + public static readonly FastFlagManager FastFlags = new(); public static readonly HttpClient HttpClient = new(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }); // shorthand @@ -194,7 +194,8 @@ namespace Bloxstrap 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(); - } + App.FastFlags.Save(); + } else if (LaunchArgs.Length > 0) { if (LaunchArgs[0].StartsWith("roblox-player:")) diff --git a/Bloxstrap/Helpers/FastFlagManager.cs b/Bloxstrap/Helpers/FastFlagManager.cs new file mode 100644 index 0000000..990eac8 --- /dev/null +++ b/Bloxstrap/Helpers/FastFlagManager.cs @@ -0,0 +1,86 @@ +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +namespace Bloxstrap.Helpers +{ + public class FastFlagManager : JsonManager> + { + public override string FileLocation => Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json"); + + // we put any changes we want to make to fastflags here + // these will apply after bloxstrap finishes installing or after the menu closes + // to delete a fastflag, set the value to null + public Dictionary Changes = new(); + + // only one missing here is Metal because lol + public static IReadOnlyDictionary RenderingModes { get; set; } = new Dictionary() + { + { "Automatic", "" }, + { "Direct3D 11", "FFlagDebugGraphicsPreferD3D11" }, + { "OpenGL", "FFlagDebugGraphicsPreferOpenGL" }, + { "Vulkan", "FFlagDebugGraphicsPreferVulkan" } + }; + + // this returns null if the fflag doesn't exist + // this also returns as a string because deserializing an object doesn't + // deserialize back into the original object type, it instead deserializes + // as a "JsonElement" which is annoying + public string? GetValue(string key) + { + // check if we have an updated change for it pushed first + if (Changes.TryGetValue(key, out object? changedValue)) + return changedValue?.ToString(); + + if (Prop.TryGetValue(key, out object? value) && value is not null) + return value.ToString(); + + return null; + } + + public void SetRenderingMode(string value) + { + foreach (var mode in RenderingModes) + { + if (value != "Automatic") + App.FastFlags.Changes[mode.Value] = null; + } + + if (value != "Automatic") + App.FastFlags.Changes[RenderingModes[value]] = true; + } + + public override void Save() + { + App.Logger.WriteLine($"[FastFlagManager::Save] Attempting to save JSON to {FileLocation}..."); + + if (Changes.Count == 0) + { + App.Logger.WriteLine($"[FastFlagManager::Save] No changes to apply, aborting."); + return; + } + + // reload for any changes made while the menu was open + Load(); + + foreach (var change in Changes) + { + if (change.Value is null) + { + App.Logger.WriteLine($"[FastFlagManager::Save] Removing '{change.Key}'"); + Prop.Remove(change.Key); + continue; + } + + App.Logger.WriteLine($"[FastFlagManager::Save] Setting '{change.Key}' to {change.Value}"); + Prop[change.Key] = change.Value; + } + + Directory.CreateDirectory(Path.GetDirectoryName(FileLocation)!); + File.WriteAllText(FileLocation, JsonSerializer.Serialize(Prop, new JsonSerializerOptions { WriteIndented = true })); + + App.Logger.WriteLine($"[FastFlagManager::Save] JSON saved!"); + } + } +} diff --git a/Bloxstrap/Helpers/JsonManager.cs b/Bloxstrap/Helpers/JsonManager.cs index 04eddef..fb59f7d 100644 --- a/Bloxstrap/Helpers/JsonManager.cs +++ b/Bloxstrap/Helpers/JsonManager.cs @@ -16,7 +16,7 @@ namespace Bloxstrap.Helpers public class JsonManager where T : new() { public T Prop { get; set; } = new(); - public string FileLocation => AltFileLocation ?? Path.Combine(Directories.Base, $"{typeof(T).Name}.json"); + public virtual string FileLocation => AltFileLocation ?? Path.Combine(Directories.Base, $"{typeof(T).Name}.json"); public string? AltFileLocation { get; set; } public void Load() @@ -35,11 +35,11 @@ namespace Bloxstrap.Helpers } } - public void Save(bool saveOverride = false) + public virtual void Save() { App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Save] Attempting to save JSON to {FileLocation}..."); - if (!App.ShouldSaveConfigs && !saveOverride) + if (!App.ShouldSaveConfigs) { App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Save] Aborted save (ShouldSave set to false)"); return; diff --git a/Bloxstrap/ViewModels/IntegrationsViewModel.cs b/Bloxstrap/ViewModels/IntegrationsViewModel.cs index e90c966..e4951b1 100644 --- a/Bloxstrap/ViewModels/IntegrationsViewModel.cs +++ b/Bloxstrap/ViewModels/IntegrationsViewModel.cs @@ -6,7 +6,6 @@ using CommunityToolkit.Mvvm.Input; using Bloxstrap.Helpers; using Bloxstrap.Models; -using Bloxstrap.Views.Pages; using System.Collections.ObjectModel; namespace Bloxstrap.ViewModels @@ -84,7 +83,11 @@ namespace Bloxstrap.ViewModels { App.Settings.Prop.UseReShade = value; ReShadePresetsEnabled = value; - OnPropertyChanged(nameof(ReShadePresetsEnabled)); + + if (value) + App.FastFlags.SetRenderingMode("Direct3D 11"); + + OnPropertyChanged(nameof(ReShadePresetsEnabled)); } } diff --git a/Bloxstrap/ViewModels/ModsViewModel.cs b/Bloxstrap/ViewModels/ModsViewModel.cs index e017b54..ca1fdce 100644 --- a/Bloxstrap/ViewModels/ModsViewModel.cs +++ b/Bloxstrap/ViewModels/ModsViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.Windows.Input; using Bloxstrap.Helpers; @@ -6,9 +7,12 @@ using CommunityToolkit.Mvvm.Input; namespace Bloxstrap.ViewModels { - public class ModsViewModel - { - public ICommand OpenModsFolderCommand => new RelayCommand(OpenModsFolder); + public class ModsViewModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler? PropertyChanged; + public void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + public ICommand OpenModsFolderCommand => new RelayCommand(OpenModsFolder); private void OpenModsFolder() { @@ -33,36 +37,21 @@ namespace Bloxstrap.ViewModels set => App.Settings.Prop.UseDisableAppPatch = value; } - // only one missing here is Metal because lol - public IReadOnlyDictionary RenderingModes { get; set; } = new Dictionary() - { - { "Automatic", "" }, - { "Direct3D 11", "FFlagDebugGraphicsPreferD3D11" }, - { "OpenGL", "FFlagDebugGraphicsPreferOpenGL" }, - { "Vulkan", "FFlagDebugGraphicsPreferVulkan" } - }; + public IReadOnlyDictionary RenderingModes => FastFlagManager.RenderingModes; - // if i ever need to do more fflag handling i'll just add an fflag handler that abstracts away all this boilerplate - // but for now this is fine + // this flag has to be set to false to work, weirdly enough public bool ExclusiveFullscreenEnabled { - get - { - return App.FastFlags.Prop.ContainsKey("FFlagHandleAltEnterFullscreenManually") && App.FastFlags.Prop["FFlagHandleAltEnterFullscreenManually"].ToString() == "False"; - } - + get => App.FastFlags.GetValue("FFlagHandleAltEnterFullscreenManually") == "False"; set { - if (!App.IsFirstRun) - App.FastFlags.Load(); + App.FastFlags.Changes["FFlagHandleAltEnterFullscreenManually"] = value ? false : null; if (value) - App.FastFlags.Prop["FFlagHandleAltEnterFullscreenManually"] = false; - else - App.FastFlags.Prop.Remove("FFlagHandleAltEnterFullscreenManually"); - - if (!App.IsFirstRun) - App.FastFlags.Save(true); + { + App.FastFlags.SetRenderingMode("Direct3D 11"); + OnPropertyChanged(nameof(SelectedRenderingMode)); + } } } @@ -72,29 +61,14 @@ namespace Bloxstrap.ViewModels { foreach (var mode in RenderingModes) { - if (App.FastFlags.Prop.ContainsKey(mode.Value)) + if (App.FastFlags.GetValue(mode.Value) == "True") return mode.Key; } return "Automatic"; } - set - { - if (!App.IsFirstRun) - App.FastFlags.Load(); - - foreach (var mode in RenderingModes) - { - App.FastFlags.Prop.Remove(mode.Value); - } - - if (value != "Automatic") - App.FastFlags.Prop[RenderingModes[value]] = true; - - if (!App.IsFirstRun) - App.FastFlags.Save(true); - } + set => App.FastFlags.SetRenderingMode(value); } public bool DisableFullscreenOptimizationsEnabled diff --git a/Bloxstrap/Views/Pages/ModsPage.xaml b/Bloxstrap/Views/Pages/ModsPage.xaml index ac4dc55..cf1610b 100644 --- a/Bloxstrap/Views/Pages/ModsPage.xaml +++ b/Bloxstrap/Views/Pages/ModsPage.xaml @@ -95,7 +95,6 @@ - @@ -106,7 +105,7 @@ - + @@ -115,7 +114,7 @@ - +