From 893aecbdd145cf9aecec38a0e63c31f0eca9c17b Mon Sep 17 00:00:00 2001 From: Matt <97983689+bluepilledgreat@users.noreply.github.com> Date: Wed, 12 Mar 2025 09:12:31 +0000 Subject: [PATCH] More arguments + debug settings (#4814) * ability to disable package cleanup * add version and channel arguments * ignore duplicate flags * fix version argument not working * add the force flag * fix compiler warnings * fix indentation --- Bloxstrap/Bootstrapper.cs | 92 ++++++++++++++++-------- Bloxstrap/Enums/LaunchMode.cs | 4 ++ Bloxstrap/LaunchSettings.cs | 22 ++++++ Bloxstrap/Models/Persistable/Settings.cs | 1 + 4 files changed, 90 insertions(+), 29 deletions(-) diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 3bf0cff..7361353 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -45,8 +45,8 @@ namespace Bloxstrap private readonly FastZipEvents _fastZipEvents = new(); private readonly CancellationTokenSource _cancelTokenSource = new(); - private readonly IAppData AppData; - private readonly LaunchMode _launchMode; + private IAppData AppData = default!; + private LaunchMode _launchMode; private string _launchCommandLine = App.LaunchSettings.RobloxLaunchArgs; private string _latestVersionGuid = null!; @@ -60,7 +60,7 @@ namespace Bloxstrap private long _totalDownloadedBytes = 0; private bool _packageExtractionSuccess = true; - private bool _mustUpgrade => String.IsNullOrEmpty(AppData.State.VersionGuid) || !File.Exists(AppData.ExecutablePath); + private bool _mustUpgrade => App.LaunchSettings.ForceFlag.Active || String.IsNullOrEmpty(AppData.State.VersionGuid) || !File.Exists(AppData.ExecutablePath); private bool _noConnection = false; private AsyncMutex? _mutex; @@ -91,6 +91,11 @@ namespace Bloxstrap _fastZipEvents.DirectoryFailure += (_, e) => throw e.Exception; _fastZipEvents.ProcessFile += (_, e) => e.ContinueRunning = !_cancelTokenSource.IsCancellationRequested; + SetupAppData(); + } + + private void SetupAppData() + { AppData = IsStudioLaunch ? new RobloxStudioData() : new RobloxPlayerData(); Deployment.BinaryType = AppData.BinaryType; } @@ -288,12 +293,17 @@ namespace Bloxstrap using var key = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\ROBLOX Corporation\\Environments\\{AppData.RegistryName}\\Channel"); var match = Regex.Match( - App.LaunchSettings.RobloxLaunchArgs, - "channel:([a-zA-Z0-9-_]+)", + App.LaunchSettings.RobloxLaunchArgs, + "channel:([a-zA-Z0-9-_]+)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant ); - if (match.Groups.Count == 2) + if (App.LaunchSettings.ChannelFlag.Active && !string.IsNullOrEmpty(App.LaunchSettings.ChannelFlag.Data)) + { + App.Logger.WriteLine(LOG_IDENT, $"Channel set to {App.LaunchSettings.ChannelFlag.Data} from arguments"); + Deployment.Channel = App.LaunchSettings.ChannelFlag.Data.ToLowerInvariant(); + } + else if (match.Groups.Count == 2) { Deployment.Channel = match.Groups[1].Value.ToLowerInvariant(); } @@ -310,29 +320,50 @@ namespace Bloxstrap if (!Deployment.IsDefaultChannel) App.SendStat("robloxChannel", Deployment.Channel); - ClientVersion clientVersion; - - try + if (!App.LaunchSettings.VersionFlag.Active || string.IsNullOrEmpty(App.LaunchSettings.VersionFlag.Data)) { - clientVersion = await Deployment.GetInfo(); + ClientVersion clientVersion; + + try + { + clientVersion = await Deployment.GetInfo(); + } + catch (InvalidChannelException ex) + { + App.Logger.WriteLine(LOG_IDENT, $"Resetting channel from {Deployment.Channel} because {ex.StatusCode}"); + + Deployment.Channel = Deployment.DefaultChannel; + clientVersion = await Deployment.GetInfo(); + } + + key.SetValueSafe("www.roblox.com", Deployment.IsDefaultChannel ? "" : Deployment.Channel); + + _latestVersionGuid = clientVersion.VersionGuid; } - catch (InvalidChannelException ex) + else { - App.Logger.WriteLine(LOG_IDENT, $"Resetting channel from {Deployment.Channel} because {ex.StatusCode}"); - - Deployment.Channel = Deployment.DefaultChannel; - clientVersion = await Deployment.GetInfo(); + App.Logger.WriteLine(LOG_IDENT, $"Version set to {App.LaunchSettings.VersionFlag.Data} from arguments"); + _latestVersionGuid = App.LaunchSettings.VersionFlag.Data; } - key.SetValueSafe("www.roblox.com", Deployment.IsDefaultChannel ? "" : Deployment.Channel); - - _latestVersionGuid = clientVersion.VersionGuid; _latestVersionDirectory = Path.Combine(Paths.Versions, _latestVersionGuid); string pkgManifestUrl = Deployment.GetLocation($"/{_latestVersionGuid}-rbxPkgManifest.txt"); var pkgManifestData = await App.HttpClient.GetStringAsync(pkgManifestUrl); _versionPackageManifest = new(pkgManifestData); + + // this can happen if version is set through arguments + if (_launchMode == LaunchMode.Unknown) + { + App.Logger.WriteLine(LOG_IDENT, "Identifying launch mode from package manifest"); + + bool isPlayer = _versionPackageManifest.Exists(x => x.Name == "RobloxApp.zip"); + App.Logger.WriteLine(LOG_IDENT, $"isPlayer: {isPlayer}"); + + _launchMode = isPlayer ? LaunchMode.Player : LaunchMode.Studio; + SetupAppData(); // we need to set it up again + } } private void StartRoblox() @@ -930,20 +961,23 @@ namespace Bloxstrap allPackageHashes.AddRange(App.State.Prop.Player.PackageHashes.Values); allPackageHashes.AddRange(App.State.Prop.Studio.PackageHashes.Values); - foreach (string hash in cachedPackageHashes) + if (!App.Settings.Prop.DebugDisableVersionPackageCleanup) { - if (!allPackageHashes.Contains(hash)) + foreach (string hash in cachedPackageHashes) { - App.Logger.WriteLine(LOG_IDENT, $"Deleting unused package {hash}"); - - try + if (!allPackageHashes.Contains(hash)) { - File.Delete(Path.Combine(Paths.Downloads, hash)); - } - catch (Exception ex) - { - App.Logger.WriteLine(LOG_IDENT, $"Failed to delete {hash}!"); - App.Logger.WriteException(LOG_IDENT, ex); + App.Logger.WriteLine(LOG_IDENT, $"Deleting unused package {hash}"); + + try + { + File.Delete(Path.Combine(Paths.Downloads, hash)); + } + catch (Exception ex) + { + App.Logger.WriteLine(LOG_IDENT, $"Failed to delete {hash}!"); + App.Logger.WriteException(LOG_IDENT, ex); + } } } } diff --git a/Bloxstrap/Enums/LaunchMode.cs b/Bloxstrap/Enums/LaunchMode.cs index c045d4f..4778442 100644 --- a/Bloxstrap/Enums/LaunchMode.cs +++ b/Bloxstrap/Enums/LaunchMode.cs @@ -3,6 +3,10 @@ public enum LaunchMode { None, + /// + /// Launch mode will be determined inside the bootstrapper. Only works if the VersionFlag is set. + /// + Unknown, Player, Studio, StudioAuth diff --git a/Bloxstrap/LaunchSettings.cs b/Bloxstrap/LaunchSettings.cs index f8492f7..bd4c36a 100644 --- a/Bloxstrap/LaunchSettings.cs +++ b/Bloxstrap/LaunchSettings.cs @@ -32,6 +32,12 @@ namespace Bloxstrap public LaunchFlag StudioFlag { get; } = new("studio"); + public LaunchFlag VersionFlag { get; } = new("version"); + + public LaunchFlag ChannelFlag { get; } = new("channel"); + + public LaunchFlag ForceFlag { get; } = new("force"); + #if DEBUG public bool BypassUpdateCheck => true; #else @@ -87,6 +93,13 @@ namespace Bloxstrap RobloxLaunchArgs = arg; startIdx = 1; } + else if (arg.StartsWith("version-")) + { + App.Logger.WriteLine(LOG_IDENT, "Got version argument"); + VersionFlag.Active = true; + VersionFlag.Data = arg; + startIdx = 1; + } } // parse @@ -108,6 +121,12 @@ namespace Bloxstrap continue; } + if (flag.Active) + { + App.Logger.WriteLine(LOG_IDENT, $"Tried to set {identifier} flag twice"); + continue; + } + flag.Active = true; if (i < Args.Length - 1 && Args[i+1] is string nextArg && !nextArg.StartsWith('-')) @@ -122,6 +141,9 @@ namespace Bloxstrap } } + if (VersionFlag.Active) + RobloxLaunchMode = LaunchMode.Unknown; // determine in bootstrapper + if (PlayerFlag.Active) ParsePlayer(PlayerFlag.Data); else if (StudioFlag.Active) diff --git a/Bloxstrap/Models/Persistable/Settings.cs b/Bloxstrap/Models/Persistable/Settings.cs index a239f31..7523cb3 100644 --- a/Bloxstrap/Models/Persistable/Settings.cs +++ b/Bloxstrap/Models/Persistable/Settings.cs @@ -17,6 +17,7 @@ namespace Bloxstrap.Models.Persistable public bool UseFastFlagManager { get; set; } = true; public bool WPFSoftwareRender { get; set; } = false; public bool EnableAnalytics { get; set; } = true; + public bool DebugDisableVersionPackageCleanup { get; set; } = false; public string? SelectedCustomTheme { get; set; } = null; // integration configuration