mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-06-23 23:00:23 -07:00
Fix handling of RBX deployment interfacing
This commit is contained in:
parent
d542efd945
commit
ce82c3faa7
@ -13,11 +13,12 @@
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Shell;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Bloxstrap.AppData;
|
||||
using System.Windows.Shell;
|
||||
using Bloxstrap.RobloxInterfaces;
|
||||
using Bloxstrap.UI.Elements.Bootstrapper.Base;
|
||||
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
@ -77,6 +78,7 @@ namespace Bloxstrap
|
||||
_fastZipEvents.ProcessFile += (_, e) => e.ContinueRunning = !_cancelTokenSource.IsCancellationRequested;
|
||||
|
||||
AppData = IsStudioLaunch ? new RobloxStudioData() : new RobloxPlayerData();
|
||||
Deployment.BinaryType = AppData.BinaryType;
|
||||
}
|
||||
|
||||
private void SetStatus(string message)
|
||||
@ -151,7 +153,7 @@ namespace Bloxstrap
|
||||
|
||||
SetStatus(Strings.Bootstrapper_Status_Connecting);
|
||||
|
||||
var connectionResult = await RobloxDeployment.InitializeConnectivity();
|
||||
var connectionResult = await Deployment.InitializeConnectivity();
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, "Connectivity check finished");
|
||||
|
||||
@ -244,29 +246,29 @@ namespace Bloxstrap
|
||||
// if it's set in the launch uri, we need to use it and set the registry key for it
|
||||
// else, check if the registry key for it exists, and use it
|
||||
|
||||
string channel = "production";
|
||||
|
||||
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-_]+)", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
|
||||
if (match.Groups.Count == 2)
|
||||
{
|
||||
channel = match.Groups[1].Value.ToLowerInvariant();
|
||||
Deployment.Channel = match.Groups[1].Value.ToLowerInvariant();
|
||||
}
|
||||
else if (key.GetValue("www.roblox.com") is string value && !String.IsNullOrEmpty(value))
|
||||
{
|
||||
channel = value;
|
||||
Deployment.Channel = value.ToLowerInvariant();
|
||||
}
|
||||
|
||||
if (channel != "production")
|
||||
App.SendStat("robloxChannel", channel);
|
||||
App.Logger.WriteLine(LOG_IDENT, "Got channel as " + (String.IsNullOrEmpty(Deployment.Channel) ? Deployment.DefaultChannel : Deployment.Channel));
|
||||
|
||||
if (Deployment.Channel != "production")
|
||||
App.SendStat("robloxChannel", Deployment.Channel);
|
||||
|
||||
ClientVersion clientVersion;
|
||||
|
||||
try
|
||||
{
|
||||
clientVersion = await RobloxDeployment.GetInfo(channel, AppData.BinaryType);
|
||||
clientVersion = await Deployment.GetInfo();
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
@ -275,25 +277,25 @@ namespace Bloxstrap
|
||||
and not HttpStatusCode.NotFound)
|
||||
throw;
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Changing channel from {channel} to {RobloxDeployment.DefaultChannel} because HTTP {(int)ex.StatusCode}");
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Changing channel from {Deployment.Channel} to {Deployment.DefaultChannel} because HTTP {(int)ex.StatusCode}");
|
||||
|
||||
channel = RobloxDeployment.DefaultChannel;
|
||||
clientVersion = await RobloxDeployment.GetInfo(channel, AppData.BinaryType);
|
||||
Deployment.Channel = Deployment.DefaultChannel;
|
||||
clientVersion = await Deployment.GetInfo();
|
||||
}
|
||||
|
||||
if (clientVersion.IsBehindDefaultChannel)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Changing channel from {channel} to {RobloxDeployment.DefaultChannel} because channel is behind production");
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Changing channel from {Deployment.Channel} to {Deployment.DefaultChannel} because channel is behind production");
|
||||
|
||||
channel = RobloxDeployment.DefaultChannel;
|
||||
clientVersion = await RobloxDeployment.GetInfo(channel, AppData.BinaryType);
|
||||
Deployment.Channel = Deployment.DefaultChannel;
|
||||
clientVersion = await Deployment.GetInfo();
|
||||
}
|
||||
|
||||
key.SetValueSafe("www.roblox.com", channel);
|
||||
key.SetValueSafe("www.roblox.com", Deployment.IsDefaultChannel ? "" : Deployment.Channel);
|
||||
|
||||
_latestVersionGuid = clientVersion.VersionGuid;
|
||||
|
||||
string pkgManifestUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-rbxPkgManifest.txt");
|
||||
string pkgManifestUrl = Deployment.GetLocation($"/{_latestVersionGuid}-rbxPkgManifest.txt");
|
||||
var pkgManifestData = await App.HttpClient.GetStringAsync(pkgManifestUrl);
|
||||
|
||||
_versionPackageManifest = new(pkgManifestData);
|
||||
@ -962,7 +964,7 @@ namespace Bloxstrap
|
||||
if (_cancelTokenSource.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
string packageUrl = RobloxDeployment.GetLocation($"/{_latestVersionGuid}-{package.Name}");
|
||||
string packageUrl = Deployment.GetLocation($"/{_latestVersionGuid}-{package.Name}");
|
||||
string robloxPackageLocation = Path.Combine(Paths.LocalAppData, "Roblox", "Downloads", package.Signature);
|
||||
|
||||
if (File.Exists(package.DownloadPath))
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace Bloxstrap.Models.Manifest
|
||||
using Bloxstrap.RobloxInterfaces;
|
||||
|
||||
namespace Bloxstrap.Models.Manifest
|
||||
{
|
||||
public class FileManifest : List<ManifestFile>
|
||||
{
|
||||
@ -24,7 +26,7 @@
|
||||
|
||||
public static async Task<FileManifest> Get(string versionGuid)
|
||||
{
|
||||
string pkgManifestUrl = RobloxDeployment.GetLocation($"/{versionGuid}-rbxManifest.txt");
|
||||
string pkgManifestUrl = Deployment.GetLocation($"/{versionGuid}-rbxManifest.txt");
|
||||
var pkgManifestData = await App.HttpClient.GetStringAsync(pkgManifestUrl);
|
||||
|
||||
return new FileManifest(pkgManifestData);
|
||||
|
@ -1,8 +1,11 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Bloxstrap
|
||||
namespace Bloxstrap.RobloxInterfaces
|
||||
{
|
||||
public class RobloxFastFlags
|
||||
// i am 100% sure there is a much, MUCH better way to handle this
|
||||
// matt wrote this so this is effectively a black box to me right now
|
||||
// i'll likely refactor this at some point
|
||||
public class ApplicationSettings
|
||||
{
|
||||
private string _applicationName;
|
||||
private string _channelName;
|
||||
@ -12,7 +15,7 @@ namespace Bloxstrap
|
||||
|
||||
private SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
|
||||
|
||||
private RobloxFastFlags(string applicationName, string channelName)
|
||||
private ApplicationSettings(string applicationName, string channelName)
|
||||
{
|
||||
_applicationName = applicationName;
|
||||
_channelName = channelName;
|
||||
@ -29,11 +32,11 @@ namespace Bloxstrap
|
||||
if (_initialised)
|
||||
return;
|
||||
|
||||
string logIndent = $"RobloxFastFlags::Fetch.{_applicationName}.{_channelName}";
|
||||
string logIndent = $"ApplicationSettings::Fetch.{_applicationName}.{_channelName}";
|
||||
App.Logger.WriteLine(logIndent, "Fetching fast flags");
|
||||
|
||||
string path = $"/v2/settings/application/{_applicationName}";
|
||||
if (_channelName != RobloxDeployment.DefaultChannel.ToLowerInvariant())
|
||||
if (_channelName != Deployment.DefaultChannel.ToLowerInvariant())
|
||||
path += $"/bucket/{_channelName}";
|
||||
|
||||
HttpResponseMessage response;
|
||||
@ -100,12 +103,13 @@ namespace Bloxstrap
|
||||
}
|
||||
|
||||
// _cache[applicationName][channelName]
|
||||
private static Dictionary<string, Dictionary<string, RobloxFastFlags>> _cache = new();
|
||||
private static Dictionary<string, Dictionary<string, ApplicationSettings>> _cache = new();
|
||||
|
||||
public static RobloxFastFlags PCDesktopClient { get; } = GetSettings("PCDesktopClient");
|
||||
public static RobloxFastFlags PCClientBootstrapper { get; } = GetSettings("PCClientBootstrapper");
|
||||
public static ApplicationSettings PCDesktopClient => GetSettings("PCDesktopClient");
|
||||
|
||||
public static RobloxFastFlags GetSettings(string applicationName, string channelName = RobloxDeployment.DefaultChannel, bool shouldCache = true)
|
||||
public static ApplicationSettings PCClientBootstrapper => GetSettings("PCClientBootstrapper");
|
||||
|
||||
public static ApplicationSettings GetSettings(string applicationName, string channelName = Deployment.DefaultChannel, bool shouldCache = true)
|
||||
{
|
||||
channelName = channelName.ToLowerInvariant();
|
||||
|
||||
@ -114,7 +118,7 @@ namespace Bloxstrap
|
||||
if (_cache.ContainsKey(applicationName) && _cache[applicationName].ContainsKey(channelName))
|
||||
return _cache[applicationName][channelName];
|
||||
|
||||
var flags = new RobloxFastFlags(applicationName, channelName);
|
||||
var flags = new ApplicationSettings(applicationName, channelName);
|
||||
|
||||
if (shouldCache)
|
||||
{
|
@ -1,11 +1,17 @@
|
||||
namespace Bloxstrap
|
||||
namespace Bloxstrap.RobloxInterfaces
|
||||
{
|
||||
public static class RobloxDeployment
|
||||
public static class Deployment
|
||||
{
|
||||
public const string DefaultChannel = "production";
|
||||
|
||||
private const string VersionStudioHash = "version-012732894899482c";
|
||||
|
||||
public static string Channel = DefaultChannel;
|
||||
|
||||
public static string BinaryType = "WindowsPlayer";
|
||||
|
||||
public static bool IsDefaultChannel => String.Compare(Channel, DefaultChannel, StringComparison.OrdinalIgnoreCase) == 0;
|
||||
|
||||
public static string BaseUrl { get; private set; } = null!;
|
||||
|
||||
private static readonly Dictionary<string, ClientVersion> ClientVersionCache = new();
|
||||
@ -23,7 +29,7 @@
|
||||
|
||||
private static async Task<string?> TestConnection(string url, int priority, CancellationToken token)
|
||||
{
|
||||
string LOG_IDENT = $"RobloxDeployment::TestConnection<{url}>";
|
||||
string LOG_IDENT = $"Deployment::TestConnection<{url}>";
|
||||
|
||||
await Task.Delay(priority * 1000, token);
|
||||
|
||||
@ -56,16 +62,14 @@
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function serves double duty as the setup mirror enumerator, and as our connectivity check.
|
||||
/// Returns null for success.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static async Task<Exception?> InitializeConnectivity()
|
||||
{
|
||||
const string LOG_IDENT = "RobloxDeployment::InitializeConnectivity";
|
||||
|
||||
// this function serves double duty as the setup mirror enumerator, and as our connectivity check
|
||||
// since we're basically asking four different urls for the exact same thing, if all four fail, then it has to be a user-side problem
|
||||
|
||||
// this should be checked for in the installer and in the bootstrapper
|
||||
|
||||
// returns null for success
|
||||
const string LOG_IDENT = "Deployment::InitializeConnectivity";
|
||||
|
||||
var tokenSource = new CancellationTokenSource();
|
||||
|
||||
@ -74,25 +78,22 @@
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, "Testing connectivity...");
|
||||
|
||||
while (tasks.Any())
|
||||
while (tasks.Any() && String.IsNullOrEmpty(BaseUrl))
|
||||
{
|
||||
var finishedTask = await Task.WhenAny(tasks);
|
||||
|
||||
if (finishedTask.IsFaulted)
|
||||
{
|
||||
tasks.Remove(finishedTask);
|
||||
exceptions.Add(finishedTask.Exception!.InnerException!);
|
||||
continue;
|
||||
}
|
||||
tasks.Remove(finishedTask);
|
||||
|
||||
BaseUrl = await finishedTask;
|
||||
break;
|
||||
if (finishedTask.IsFaulted)
|
||||
exceptions.Add(finishedTask.Exception!.InnerException!);
|
||||
else
|
||||
BaseUrl = finishedTask.Result;
|
||||
}
|
||||
|
||||
// stop other running connectivity tests
|
||||
tokenSource.Cancel();
|
||||
|
||||
if (String.IsNullOrEmpty(BaseUrl))
|
||||
if (string.IsNullOrEmpty(BaseUrl))
|
||||
return exceptions[0];
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Got {BaseUrl} as the optimal base URL");
|
||||
@ -100,18 +101,18 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetLocation(string resource, string channel = DefaultChannel)
|
||||
public static string GetLocation(string resource)
|
||||
{
|
||||
string location = BaseUrl;
|
||||
|
||||
if (String.Compare(channel, DefaultChannel, StringComparison.InvariantCultureIgnoreCase) != 0)
|
||||
if (!IsDefaultChannel)
|
||||
{
|
||||
string channelName;
|
||||
|
||||
if (RobloxFastFlags.GetSettings(nameof(RobloxFastFlags.PCClientBootstrapper), channel).Get<bool>("FFlagReplaceChannelNameForDownload"))
|
||||
if (ApplicationSettings.GetSettings(nameof(ApplicationSettings.PCClientBootstrapper), Channel).Get<bool>("FFlagReplaceChannelNameForDownload"))
|
||||
channelName = "common";
|
||||
else
|
||||
channelName = channel.ToLowerInvariant();
|
||||
channelName = Channel.ToLowerInvariant();
|
||||
|
||||
location += $"/channel/{channelName}";
|
||||
}
|
||||
@ -121,16 +122,18 @@
|
||||
return location;
|
||||
}
|
||||
|
||||
public static async Task<ClientVersion> GetInfo(string channel, string binaryType = "WindowsPlayer")
|
||||
public static async Task<ClientVersion> GetInfo(string? channel = null)
|
||||
{
|
||||
const string LOG_IDENT = "RobloxDeployment::GetInfo";
|
||||
const string LOG_IDENT = "Deployment::GetInfo";
|
||||
|
||||
if (String.IsNullOrEmpty(channel))
|
||||
channel = Channel;
|
||||
|
||||
bool isDefaultChannel = String.Compare(channel, DefaultChannel, StringComparison.OrdinalIgnoreCase) == 0;
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Getting deploy info for channel {channel}");
|
||||
|
||||
if (String.IsNullOrEmpty(channel))
|
||||
channel = DefaultChannel;
|
||||
|
||||
string cacheKey = $"{channel}-{binaryType}";
|
||||
string cacheKey = $"{channel}-{BinaryType}";
|
||||
|
||||
ClientVersion clientVersion;
|
||||
|
||||
@ -141,12 +144,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isDefaultChannel = String.Compare(channel, DefaultChannel, StringComparison.OrdinalIgnoreCase) == 0;
|
||||
|
||||
string path = $"/v2/client-version/{binaryType}";
|
||||
string path = $"/v2/client-version/{BinaryType}";
|
||||
|
||||
if (!isDefaultChannel)
|
||||
path = $"/v2/client-version/{binaryType}/channel/{channel}";
|
||||
path = $"/v2/client-version/{BinaryType}/channel/{channel}";
|
||||
|
||||
try
|
||||
{
|
Loading…
Reference in New Issue
Block a user