Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring back the old Roblox version directory #3908

Merged
merged 1 commit into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Bloxstrap/AppData/CommonAppData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ public abstract class CommonAppData
};

public virtual string ExecutableName { get; } = null!;

public virtual string Directory { get; } = null!;

public string LockFilePath => Path.Combine(Directory, "Bloxstrap.lock");
public string Directory => Path.Combine(Paths.Versions, State.VersionGuid);

public string ExecutablePath => Path.Combine(Directory, ExecutableName);


public virtual AppState State { get; } = null!;

public virtual IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; }


Expand Down
4 changes: 0 additions & 4 deletions Bloxstrap/AppData/IAppData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ internal interface IAppData

string Directory { get; }

string OldDirectory { get; }

string LockFilePath { get; }

string ExecutablePath { get; }

AppState State { get; }
Expand Down
6 changes: 1 addition & 5 deletions Bloxstrap/AppData/RobloxPlayerData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ public class RobloxPlayerData : CommonAppData, IAppData

public override string ExecutableName => "RobloxPlayerBeta.exe";

public override string Directory => Path.Combine(Paths.Roblox, "Player");

public string OldDirectory => Path.Combine(Paths.Roblox, "Player.old");

public AppState State => App.State.Prop.Player;
public override AppState State => App.State.Prop.Player;

public override IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; } = new Dictionary<string, string>()
{
Expand Down
6 changes: 1 addition & 5 deletions Bloxstrap/AppData/RobloxStudioData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ public class RobloxStudioData : CommonAppData, IAppData

public override string ExecutableName => "RobloxStudioBeta.exe";

public override string Directory => Path.Combine(Paths.Roblox, "Studio");

public string OldDirectory => Path.Combine(Paths.Roblox, "Studio.old");

public AppState State => App.State.Prop.Studio;
public override AppState State => App.State.Prop.Studio;

public override IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; } = new Dictionary<string, string>()
{
Expand Down
4 changes: 2 additions & 2 deletions Bloxstrap/Bloxstrap.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<UseWPF>true</UseWPF>
<UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Bloxstrap.ico</ApplicationIcon>
<Version>2.8.1</Version>
<FileVersion>2.8.1</FileVersion>
<Version>2.8.2</Version>
<FileVersion>2.8.2</FileVersion>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
Expand Down
123 changes: 60 additions & 63 deletions Bloxstrap/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class Bootstrapper

private string _launchCommandLine = App.LaunchSettings.RobloxLaunchArgs;
private string _latestVersionGuid = null!;
private string _latestVersionDirectory = null!;
private PackageManifest _versionPackageManifest = null!;

private bool _isInstalling = false;
Expand All @@ -58,7 +59,7 @@ public class Bootstrapper
private double _taskbarProgressMaximum;
private long _totalDownloadedBytes = 0;

private bool _mustUpgrade => String.IsNullOrEmpty(AppData.State.VersionGuid) || File.Exists(AppData.LockFilePath) || !File.Exists(AppData.ExecutablePath);
private bool _mustUpgrade => String.IsNullOrEmpty(AppData.State.VersionGuid) || !File.Exists(AppData.ExecutablePath);
private bool _noConnection = false;

private AsyncMutex? _mutex;
Expand Down Expand Up @@ -313,6 +314,7 @@ private async Task GetLatestVersionInfo()
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);
Expand Down Expand Up @@ -513,18 +515,13 @@ public void Cancel()
try
{
// clean up install
if (Directory.Exists(AppData.Directory))
Directory.Delete(AppData.Directory, true);
if (Directory.Exists(_latestVersionDirectory))
Directory.Delete(_latestVersionDirectory, true);
}
catch (Exception ex)
{
App.Logger.WriteLine(LOG_IDENT, "Could not fully clean up installation!");
App.Logger.WriteException(LOG_IDENT, ex);

// assurance to make sure the next launch does a fresh install
// we probably shouldn't be using the lockfile to do this, but meh
var lockFile = new FileInfo(AppData.LockFilePath);
lockFile.Create().Dispose();
}
}
else if (_appPid != 0)
Expand Down Expand Up @@ -649,69 +646,67 @@ private async Task<bool> CheckForUpdates()

return false;
}
#endregion
#endregion

#region Roblox Install
private async Task UpgradeRoblox()
private void CleanupVersionsFolder()
{
const string LOG_IDENT = "Bootstrapper::UpgradeRoblox";

if (String.IsNullOrEmpty(AppData.State.VersionGuid))
SetStatus(Strings.Bootstrapper_Status_Installing);
else
SetStatus(Strings.Bootstrapper_Status_Upgrading);

Directory.CreateDirectory(Paths.Base);
Directory.CreateDirectory(Paths.Downloads);
Directory.CreateDirectory(Paths.Roblox);
const string LOG_IDENT = "Bootstrapper::CleanupVersionsFolder";

if (Directory.Exists(AppData.Directory))
foreach (string dir in Directory.GetDirectories(Paths.Versions))
{
if (Directory.Exists(AppData.OldDirectory))
Directory.Delete(AppData.OldDirectory, true);
string dirName = Path.GetFileName(dir);

try
{
// test to see if any files are in use
// if you have a better way to check for this, please let me know!
Directory.Move(AppData.Directory, AppData.OldDirectory);
}
catch (Exception ex)
if (dirName != App.State.Prop.Player.VersionGuid && dirName != App.State.Prop.Studio.VersionGuid)
{
App.Logger.WriteLine(LOG_IDENT, "Could not clear old files, aborting update.");
App.Logger.WriteException(LOG_IDENT, ex);

// 0x80070020 is the HRESULT that indicates that a process is still running
// (either RobloxPlayerBeta or RobloxCrashHandler), so we'll silently ignore it
if ((uint)ex.HResult != 0x80070020)
try
{
Directory.Delete(dir, true);
}
catch (IOException ex)
{
// ensure no files are marked as read-only for good measure
foreach (var file in Directory.GetFiles(AppData.Directory, "*", SearchOption.AllDirectories))
Filesystem.AssertReadOnly(file);
App.Logger.WriteLine(LOG_IDENT, $"Failed to delete {dir}");
App.Logger.WriteException(LOG_IDENT, ex);
}
}
}
}

Frontend.ShowMessageBox(
Strings.Bootstrapper_FilesInUse,
_mustUpgrade ? MessageBoxImage.Error : MessageBoxImage.Warning
);
private void MigrateCompatibilityFlags()
{
const string LOG_IDENT = "Bootstrapper::MigrateCompatibilityFlags";

if (_mustUpgrade)
App.Terminate(ErrorCode.ERROR_CANCELLED);
}
string oldClientLocation = Path.Combine(Paths.Versions, AppData.State.VersionGuid, AppData.ExecutableName);
string newClientLocation = Path.Combine(_latestVersionDirectory, AppData.ExecutableName);

return;
}
// move old compatibility flags for the old location
using RegistryKey appFlagsKey = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers");
string? appFlags = appFlagsKey.GetValue(oldClientLocation) as string;

Directory.Delete(AppData.OldDirectory, true);
if (appFlags is not null)
{
App.Logger.WriteLine(LOG_IDENT, $"Migrating app compatibility flags from {oldClientLocation} to {newClientLocation}...");
appFlagsKey.SetValueSafe(newClientLocation, appFlags);
appFlagsKey.DeleteValueSafe(oldClientLocation);
}
}

_isInstalling = true;
private async Task UpgradeRoblox()
{
const string LOG_IDENT = "Bootstrapper::UpgradeRoblox";

Directory.CreateDirectory(AppData.Directory);
if (String.IsNullOrEmpty(AppData.State.VersionGuid))
SetStatus(Strings.Bootstrapper_Status_Installing);
else
SetStatus(Strings.Bootstrapper_Status_Upgrading);

Directory.CreateDirectory(Paths.Base);
Directory.CreateDirectory(Paths.Downloads);
Directory.CreateDirectory(Paths.Versions);

_isInstalling = true;

// installer lock, it should only be present while roblox is in the process of upgrading
// if it's present while we're launching, then it's an unfinished install and must be reinstalled
var lockFile = new FileInfo(AppData.LockFilePath);
lockFile.Create().Dispose();
Directory.CreateDirectory(_latestVersionDirectory);

var cachedPackageHashes = Directory.GetFiles(Paths.Downloads).Select(x => Path.GetFileName(x));

Expand Down Expand Up @@ -779,7 +774,7 @@ private async Task UpgradeRoblox()
await Task.WhenAll(extractionTasks);

App.Logger.WriteLine(LOG_IDENT, "Writing AppSettings.xml...");
await File.WriteAllTextAsync(Path.Combine(AppData.Directory, "AppSettings.xml"), AppSettings);
await File.WriteAllTextAsync(Path.Combine(_latestVersionDirectory, "AppSettings.xml"), AppSettings);

if (_cancelTokenSource.IsCancellationRequested)
return;
Expand Down Expand Up @@ -814,7 +809,7 @@ private async Task UpgradeRoblox()
return;
}

string baseDirectory = Path.Combine(AppData.Directory, AppData.PackageDirectoryMap[package.Name]);
string baseDirectory = Path.Combine(_latestVersionDirectory, AppData.PackageDirectoryMap[package.Name]);

ExtractPackage(package);

Expand All @@ -838,13 +833,17 @@ private async Task UpgradeRoblox()

// finishing and cleanup

MigrateCompatibilityFlags();

AppData.State.VersionGuid = _latestVersionGuid;

AppData.State.PackageHashes.Clear();

foreach (var package in _versionPackageManifest)
AppData.State.PackageHashes.Add(package.Name, package.Signature);

CleanupVersionsFolder();

var allPackageHashes = new List<string>();

allPackageHashes.AddRange(App.State.Prop.Player.PackageHashes.Values);
Expand Down Expand Up @@ -885,8 +884,6 @@ private async Task UpgradeRoblox()

App.State.Save();

lockFile.Delete();

_isInstalling = false;
}

Expand Down Expand Up @@ -919,7 +916,7 @@ private async Task ApplyModifications()

const string path = "rbxasset://fonts/CustomFont.ttf";

foreach (string jsonFilePath in Directory.GetFiles(Path.Combine(AppData.Directory, "content\\fonts\\families")))
foreach (string jsonFilePath in Directory.GetFiles(Path.Combine(_latestVersionDirectory, "content\\fonts\\families")))
{
string jsonFilename = Path.GetFileName(jsonFilePath);
string modFilepath = Path.Combine(modFontFamiliesFolder, jsonFilename);
Expand Down Expand Up @@ -980,7 +977,7 @@ private async Task ApplyModifications()
modFolderFiles.Add(relativeFile);

string fileModFolder = Path.Combine(Paths.Modifications, relativeFile);
string fileVersionFolder = Path.Combine(AppData.Directory, relativeFile);
string fileVersionFolder = Path.Combine(_latestVersionDirectory, relativeFile);

if (File.Exists(fileVersionFolder) && MD5Hash.FromFile(fileModFolder) == MD5Hash.FromFile(fileVersionFolder))
{
Expand Down Expand Up @@ -1016,7 +1013,7 @@ private async Task ApplyModifications()
{
App.Logger.WriteLine(LOG_IDENT, $"{fileLocation} was removed as a mod but does not belong to a package");

string versionFileLocation = Path.Combine(AppData.Directory, fileLocation);
string versionFileLocation = Path.Combine(_latestVersionDirectory, fileLocation);

if (File.Exists(versionFileLocation))
File.Delete(versionFileLocation);
Expand Down Expand Up @@ -1204,7 +1201,7 @@ private void ExtractPackage(Package package, List<string>? files = null)
return;
}

string packageFolder = Path.Combine(AppData.Directory, packageDir);
string packageFolder = Path.Combine(_latestVersionDirectory, packageDir);
string? fileFilter = null;

// for sharpziplib, each file in the filter needs to be a regex
Expand Down
14 changes: 14 additions & 0 deletions Bloxstrap/Extensions/RegistryKeyEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,19 @@ public static void SetValueSafe(this RegistryKey registryKey, string? name, obje
App.Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
}
}

public static void DeleteValueSafe(this RegistryKey registryKey, string name)
{
try
{
App.Logger.WriteLine("RegistryKeyEx::DeleteValueSafe", $"Deleting {registryKey}\\{name}");
registryKey.DeleteValue(name);
}
catch (UnauthorizedAccessException)
{
Frontend.ShowMessageBox(Strings.Dialog_RegistryWriteError, System.Windows.MessageBoxImage.Error);
App.Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
}
}
}
}
22 changes: 12 additions & 10 deletions Bloxstrap/Installer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ public static void DoUninstall(bool keepData)

() => File.Delete(StartMenuShortcut),

() => Directory.Delete(Paths.Versions, true),
() => Directory.Delete(Paths.Downloads, true),
() => Directory.Delete(Paths.Roblox, true),

() => File.Delete(App.State.FileLocation)
};
Expand Down Expand Up @@ -547,15 +547,6 @@ public static void HandleUpgrade()

App.FastFlags.SetValue("FFlagDisableNewIGMinDUA", null);
App.FastFlags.SetValue("FFlagFixGraphicsQuality", null);

try
{
Directory.Delete(Path.Combine(Paths.Base, "Versions"), true);
}
catch (Exception ex)
{
App.Logger.WriteException(LOG_IDENT, ex);
}
}

if (Utilities.CompareVersions(existingVer, "2.8.1") == VersionComparison.LessThan)
Expand All @@ -572,6 +563,17 @@ public static void HandleUpgrade()
App.FastFlags.SetValue("FFlagEnableInGameMenuChromeABTest4", null);
}

if (Utilities.CompareVersions(existingVer, "2.8.2") == VersionComparison.LessThan)
{
try
{
Directory.Delete(Path.Combine(Paths.Base, "Roblox"), true);
}
catch (Exception ex)
{
App.Logger.WriteException(LOG_IDENT, ex);
}
}

App.Settings.Save();
App.FastFlags.Save();
Expand Down
3 changes: 2 additions & 1 deletion Bloxstrap/Models/Entities/ActivityData.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Web;
using System.Windows;
using System.Windows.Input;
using Bloxstrap.AppData;
using Bloxstrap.Models.APIs;
using CommunityToolkit.Mvvm.Input;

Expand Down Expand Up @@ -149,7 +150,7 @@ public string GetInviteDeeplink(bool launchData = true)

private void RejoinServer()
{
string playerPath = Path.Combine(Paths.Roblox, "Player", "RobloxPlayerBeta.exe");
string playerPath = new RobloxPlayerData().ExecutablePath;

Process.Start(playerPath, GetInviteDeeplink(false));
}
Expand Down
Loading