diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 2a76009..cd8399a 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -43,6 +43,7 @@ namespace Bloxstrap 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 HttpClientLoggingHandler( @@ -178,6 +179,7 @@ namespace Bloxstrap Settings.Load(); State.Load(); + FastFlags.Load(); } if (!IsUninstall && !IsMenuLaunch) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 981f475..72f69f5 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -193,6 +193,7 @@ namespace Bloxstrap await InstallWebView2(); + App.FastFlags.Save(); await ApplyModifications(); if (App.IsFirstRun || FreshInstall) diff --git a/Bloxstrap/FastFlagManager.cs b/Bloxstrap/FastFlagManager.cs new file mode 100644 index 0000000..26599fd --- /dev/null +++ b/Bloxstrap/FastFlagManager.cs @@ -0,0 +1,229 @@ +using System.Windows.Forms; + +using Windows.Win32; +using Windows.Win32.Graphics.Gdi; + +namespace Bloxstrap +{ + public class FastFlagManager : JsonManager> + { + public override string FileLocation => Path.Combine(Paths.Modifications, "ClientSettings\\ClientAppSettings.json"); + + // 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]}}"; + + public static IReadOnlyDictionary PresetFlags = new Dictionary + { + { "Network.Log", "FLogNetwork" }, + + { "HTTP.Log", "DFLogHttpTraceLight" }, + + { "HTTP.Proxy.Enable", "DFFlagDebugEnableHttpProxy" }, + { "HTTP.Proxy.Address.1", "DFStringDebugPlayerHttpProxyUrl" }, + { "HTTP.Proxy.Address.2", "DFStringHttpCurlProxyHostAndPort" }, + { "HTTP.Proxy.Address.3", "DFStringHttpCurlProxyHostAndPortForExternalUrl" }, + + { "Rendering.Framerate", "DFIntTaskSchedulerTargetFps" }, + { "Rendering.ManualFullscreen", "FFlagHandleAltEnterFullscreenManually" }, + { "Rendering.TexturePack", "FStringPartTexturePackTable2022" }, + { "Rendering.DisableScaling", "DFFlagDisableDPIScale" }, + + { "Rendering.Lighting.Voxel", "DFFlagDebugRenderForceTechnologyVoxel" }, + { "Rendering.Lighting.ShadowMap", "FFlagDebugForceFutureIsBrightPhase2" }, + { "Rendering.Lighting.Future", "FFlagDebugForceFutureIsBrightPhase3" }, + + { "UI.Hide", "DFIntCanHideGuiGroupId" }, + { "UI.FlagState", "FStringDebugShowFlagState" }, + + { "UI.Menu.GraphicsSlider", "FFlagFixGraphicsQuality" }, + + { "UI.Menu.Style.DisableV2", "FFlagDisableNewIGMinDUA" }, + { "UI.Menu.Style.EnableV4.1", "FFlagEnableInGameMenuControls" }, + { "UI.Menu.Style.EnableV4.2", "FFlagEnableInGameMenuModernization" }, + + { "UI.Menu.Style.ABTest.1", "FFlagEnableMenuControlsABTest" }, + { "UI.Menu.Style.ABTest.2", "FFlagEnableMenuModernizationABTest" }, + { "UI.Menu.Style.ABTest.3", "FFlagEnableMenuModernizationABTest2" }, + { "UI.Menu.Style.ABTest.4", "FFlagEnableV3MenuABTest3" } + }; + + public static IReadOnlyDictionary LightingModes => new Dictionary + { + { "Chosen by game", "None" }, + { "Voxel (Phase 1)", "Voxel" }, + { "ShadowMap (Phase 2)", "ShadowMap" }, + { "Future (Phase 3)", "Future" } + }; + + public static IReadOnlyDictionary MSAAModes => new Dictionary + { + { "Automatic", null }, + { "1x MSAA", "1" }, + { "2x MSAA", "2" }, + { "4x MSAA", "4" }, + { "8x MSAA", "8" } + }; + + // 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> + { + { + "Default", + new Dictionary + { + { "DisableV2", null }, + { "EnableV4", null }, + { "ABTest", null } + } + }, + + { + "Version 1 (2015)", + new Dictionary + { + { "DisableV2", "True" }, + { "EnableV4", "False" }, + { "ABTest", "False" } + } + }, + + { + "Version 2 (2020)", + new Dictionary + { + { "DisableV2", "False" }, + { "EnableV4", "False" }, + { "ABTest", "False" } + } + }, + + { + "Version 4 (2023)", + new Dictionary + { + { "DisableV2", "True" }, + { "EnableV4", "True" }, + { "ABTest", "False" } + } + } + }; + + // all fflags are stored as strings + // to delete a flag, set the value as null + public void SetValue(string key, object? value) + { + const string LOG_IDENT = "FastFlagManager::SetValue"; + + if (value is null) + { + if (Prop.ContainsKey(key)) + App.Logger.WriteLine(LOG_IDENT, $"Deletion of '{key}' is pending"); + + Prop.Remove(key); + } + else + { + if (Prop.ContainsKey(key)) + { + if (key == Prop[key].ToString()) + return; + + App.Logger.WriteLine(LOG_IDENT, $"Changing of '{key}' from '{Prop[key]}' to '{value}' is pending"); + } + else + { + App.Logger.WriteLine(LOG_IDENT, $"Setting of '{key}' to '{value}' is pending"); + } + + Prop[key] = value.ToString()!; + } + } + + // this returns null if the fflag doesn't exist + public string? GetValue(string key) + { + // check if we have an updated change for it pushed first + if (Prop.TryGetValue(key, out object? value) && value is not null) + return value.ToString(); + + return null; + } + + public void SetPreset(string prefix, object? value) + { + foreach (var pair in PresetFlags.Where(x => x.Key.StartsWith(prefix))) + SetValue(pair.Value, value); + } + + public void SetPresetEnum(string prefix, string target, object? value) + { + foreach (var pair in PresetFlags.Where(x => x.Key.StartsWith(prefix))) + { + if (pair.Key.StartsWith($"{prefix}.{target}")) + SetValue(pair.Value, value); + else + SetValue(pair.Value, null); + } + } + + public string? GetPreset(string name) => GetValue(PresetFlags[name]); + + public string GetPresetEnum(IReadOnlyDictionary mapping, string prefix, string value) + { + foreach (var pair in mapping) + { + if (pair.Value == "None") + continue; + + if (GetPreset($"{prefix}.{pair.Value}") == value) + return pair.Key; + } + + return mapping.First().Key; + } + + public override void Save() + { + // convert all flag values to strings before saving + + foreach (var pair in Prop) + Prop[pair.Key] = pair.Value.ToString()!; + + base.Save(); + } + + public override void Load() + { + base.Load(); + + if (GetPreset("Rendering.ManualFullscreen") != "False") + SetPreset("Rendering.ManualFullscreen", "False"); + + // TODO - remove when activity tracking has been revamped + if (GetPreset("Network.Log") != "7") + SetPreset("Network.Log", "7"); + + string? val = GetPreset("UI.Menu.Style.EnableV4.1"); + if (GetPreset("UI.Menu.Style.EnableV4.2") != val) + SetPreset("UI.Menu.Style.EnableV4.2", val); + + if (GetPreset("Rendering.Framerate") is not null) + return; + + // set it to be the framerate of the primary display by default + + var screen = Screen.AllScreens.Where(x => x.Primary).Single(); + var devmode = new DEVMODEW(); + + PInvoke.EnumDisplaySettings(screen.DeviceName, ENUM_DISPLAY_SETTINGS_MODE.ENUM_CURRENT_SETTINGS, ref devmode); + + uint framerate = devmode.dmDisplayFrequency; + + if (framerate <= 100) + framerate *= 2; + + SetPreset("Rendering.Framerate", framerate); + } + } +} diff --git a/Bloxstrap/InstallChecker.cs b/Bloxstrap/InstallChecker.cs index 5cde3c1..3744e84 100644 --- a/Bloxstrap/InstallChecker.cs +++ b/Bloxstrap/InstallChecker.cs @@ -131,6 +131,7 @@ namespace Bloxstrap App.IsSetupComplete = false; + App.FastFlags.Load(); Controls.ShowMenu(); // exit if we don't click the install button on installation @@ -209,6 +210,37 @@ namespace Bloxstrap Bootstrapper.Register(); + // update migrations + + if (App.BuildMetadata.CommitRef.StartsWith("tag")) + { + if (existingVersionInfo.ProductVersion == "2.4.0") + { + App.FastFlags.SetValue("DFFlagDisableDPIScale", null); + App.FastFlags.SetValue("DFFlagVariableDPIScale2", null); + App.FastFlags.Save(); + } + else if (existingVersionInfo.ProductVersion == "2.5.0") + { + App.FastFlags.SetValue("FIntDebugForceMSAASamples", null); + + if (App.FastFlags.GetPreset("UI.Menu.Style.DisableV2") is not null) + App.FastFlags.SetPreset("UI.Menu.Style.ABTest", false); + + App.FastFlags.Save(); + } + else if (existingVersionInfo.ProductVersion == "2.5.3") + { + App.FastFlags.SetValue("FFlagDebugGraphicsPreferD3D11", null); + App.FastFlags.SetValue("FFlagDebugGraphicsPreferD3D11FL10", null); + App.FastFlags.SetValue("FFlagDebugGraphicsPreferVulkan", null); + App.FastFlags.SetValue("FFlagRenderVulkanFixMinimizeWindow", null); + App.FastFlags.SetValue("FFlagDebugGraphicsPreferOpenGL", null); + + App.FastFlags.Save(); + } + } + if (isAutoUpgrade) { App.NotifyIcon?.ShowAlert( diff --git a/Bloxstrap/Models/FastFlag.cs b/Bloxstrap/Models/FastFlag.cs new file mode 100644 index 0000000..e2372e1 --- /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/Dialogs/AddFastFlagDialog.xaml b/Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml new file mode 100644 index 0000000..3a47528 --- /dev/null +++ b/Bloxstrap/UI/Elements/Dialogs/AddFastFlagDialog.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +