Follow up on FastFlag modding implementation

took me 2 days to think of this mfw
This commit is contained in:
pizzaboxer 2023-03-11 23:52:53 +00:00
parent 04fd634784
commit fdc9f9b1bc
6 changed files with 116 additions and 53 deletions

View File

@ -47,7 +47,7 @@ namespace Bloxstrap
public static readonly DeployManager DeployManager = new();
public static readonly JsonManager<Settings> Settings = new();
public static readonly JsonManager<State> State = new();
public static readonly JsonManager<Dictionary<string, object>> FastFlags = new();
public static readonly FastFlagManager FastFlags = new();
public static readonly HttpClient HttpClient = new(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All });
// shorthand
@ -194,6 +194,7 @@ 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)
{

View File

@ -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<Dictionary<string, object>>
{
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<string, object?> Changes = new();
// only one missing here is Metal because lol
public static IReadOnlyDictionary<string, string> RenderingModes { get; set; } = new Dictionary<string, string>()
{
{ "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!");
}
}
}

View File

@ -16,7 +16,7 @@ namespace Bloxstrap.Helpers
public class JsonManager<T> 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;

View File

@ -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,6 +83,10 @@ namespace Bloxstrap.ViewModels
{
App.Settings.Prop.UseReShade = value;
ReShadePresetsEnabled = value;
if (value)
App.FastFlags.SetRenderingMode("Direct3D 11");
OnPropertyChanged(nameof(ReShadePresetsEnabled));
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Input;
using Bloxstrap.Helpers;
@ -6,8 +7,11 @@ using CommunityToolkit.Mvvm.Input;
namespace Bloxstrap.ViewModels
{
public class ModsViewModel
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<string, string> RenderingModes { get; set; } = new Dictionary<string, string>()
{
{ "Automatic", "" },
{ "Direct3D 11", "FFlagDebugGraphicsPreferD3D11" },
{ "OpenGL", "FFlagDebugGraphicsPreferOpenGL" },
{ "Vulkan", "FFlagDebugGraphicsPreferVulkan" }
};
public IReadOnlyDictionary<string, string> 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

View File

@ -95,7 +95,6 @@
</Grid>
<TextBlock Text="FastFlags" FontSize="16" FontWeight="Medium" Margin="0,16,0,0" />
<TextBlock Text="Note that these changes automatically save to allow for ClientAppSettings.json to be manually edited." FontSize="12" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
@ -106,7 +105,7 @@
<ui:CardControl.Header>
<StackPanel>
<TextBlock FontSize="14" Text="Use exclusive fullscreen" />
<TextBlock Margin="0,2,0,0" FontSize="12" Text="Enables using Alt + Enter to enter exclusive fullscreen. Requires Direct3D 11." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
<TextBlock Margin="0,2,0,0" FontSize="12" Text="Enables using Alt + Enter to enter exclusive fullscreen. Only works with Direct3D 11." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
</StackPanel>
</ui:CardControl.Header>
<ui:ToggleSwitch IsChecked="{Binding ExclusiveFullscreenEnabled, Mode=TwoWay}" />
@ -115,7 +114,7 @@
<ui:CardControl.Header>
<StackPanel>
<TextBlock FontSize="14" Text="Rendering mode" />
<TextBlock Margin="0,2,0,0" FontSize="12" Text="Choose which renderer Roblox should use. ReShade requires Direct3D 11." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
<TextBlock Margin="0,2,0,0" FontSize="12" Text="Select which renderer Roblox should use. ReShade requires Direct3D 11." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
</StackPanel>
</ui:CardControl.Header>
<ComboBox Margin="5,0,0,0" Padding="10,5,10,5" Width="200" ItemsSource="{Binding RenderingModes.Keys, Mode=OneTime}" Text="{Binding SelectedRenderingMode, Mode=TwoWay}" />