mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Merge remote-tracking branch 'real/main' into user-pfp-discord-rpc
This commit is contained in:
commit
530bb84095
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -8,6 +8,7 @@ body:
|
||||
### **Preliminary instructions**
|
||||
- Before opening an issue, please [check the Wiki first](https://github.com/pizzaboxer/bloxstrap/wiki/) to see if your problem has been addressed there.
|
||||
- If it isn't, please confirm which pages that you read that were relevant to your issue.
|
||||
- Your issue ***will*** be closed without warning if there's a Wiki page addressing your problem.
|
||||
- If your problem is with Roblox itself (i.e. it crashes or doesn't launch), [check to see if it happens without Bloxstrap](https://github.com/pizzaboxer/bloxstrap/wiki/Roblox-crashes-or-does-not-launch).
|
||||
- Please only open an issue if your problem happens only with Bloxstrap, and state clearly that this is the case, as anything else is out of my control.
|
||||
- If you are getting a Bloxstrap Exception error, please attach a copy of the provided log file. There is a button on the dialog that locates it for you.
|
||||
|
@ -57,21 +57,13 @@ namespace Bloxstrap
|
||||
|
||||
private static bool _showingExceptionDialog = false;
|
||||
|
||||
private static bool _terminating = false;
|
||||
|
||||
public static void Terminate(ErrorCode exitCode = ErrorCode.ERROR_SUCCESS)
|
||||
{
|
||||
if (_terminating)
|
||||
return;
|
||||
|
||||
int exitCodeNum = (int)exitCode;
|
||||
|
||||
Logger.WriteLine("App::Terminate", $"Terminating with exit code {exitCodeNum} ({exitCode})");
|
||||
|
||||
Current.Dispatcher.Invoke(() => Current.Shutdown(exitCodeNum));
|
||||
// Environment.Exit(exitCodeNum);
|
||||
|
||||
_terminating = true;
|
||||
Environment.Exit(exitCodeNum);
|
||||
}
|
||||
|
||||
void GlobalExceptionHandler(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
@ -101,8 +93,7 @@ namespace Bloxstrap
|
||||
|
||||
_showingExceptionDialog = true;
|
||||
|
||||
if (!LaunchSettings.QuietFlag.Active)
|
||||
Frontend.ShowExceptionDialog(ex);
|
||||
Frontend.ShowExceptionDialog(ex);
|
||||
|
||||
Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
|
||||
}
|
||||
@ -110,6 +101,7 @@ namespace Bloxstrap
|
||||
public static async Task<GithubRelease?> GetLatestRelease()
|
||||
{
|
||||
const string LOG_IDENT = "App::GetLatestRelease";
|
||||
|
||||
try
|
||||
{
|
||||
var releaseInfo = await Http.GetJson<GithubRelease>($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
|
||||
@ -199,6 +191,26 @@ namespace Bloxstrap
|
||||
}
|
||||
}
|
||||
|
||||
if (fixInstallLocation && installLocation is not null)
|
||||
{
|
||||
var installer = new Installer
|
||||
{
|
||||
InstallLocation = installLocation,
|
||||
IsImplicitInstall = true
|
||||
};
|
||||
|
||||
if (installer.CheckInstallLocation())
|
||||
{
|
||||
Logger.WriteLine(LOG_IDENT, $"Changing install location to '{installLocation}'");
|
||||
installer.DoInstall();
|
||||
}
|
||||
else
|
||||
{
|
||||
// force reinstall
|
||||
installLocation = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (installLocation is null)
|
||||
{
|
||||
Logger.Initialize(true);
|
||||
@ -206,21 +218,6 @@ namespace Bloxstrap
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fixInstallLocation)
|
||||
{
|
||||
var installer = new Installer
|
||||
{
|
||||
InstallLocation = installLocation,
|
||||
IsImplicitInstall = true
|
||||
};
|
||||
|
||||
if (installer.CheckInstallLocation())
|
||||
{
|
||||
Logger.WriteLine(LOG_IDENT, $"Changing install location to '{installLocation}'");
|
||||
installer.DoInstall();
|
||||
}
|
||||
}
|
||||
|
||||
Paths.Initialize(installLocation);
|
||||
|
||||
// ensure executable is in the install directory
|
||||
@ -247,10 +244,8 @@ namespace Bloxstrap
|
||||
|
||||
Locale.Set(Settings.Prop.Locale);
|
||||
|
||||
#if !DEBUG
|
||||
if (!LaunchSettings.BypassUpdateCheck)
|
||||
Installer.HandleUpgrade();
|
||||
#endif
|
||||
|
||||
LaunchHandler.ProcessLaunchArgs();
|
||||
}
|
||||
|
@ -39,8 +39,17 @@ namespace Bloxstrap.AppData
|
||||
{ "extracontent-places.zip", @"ExtraContent\places\" },
|
||||
};
|
||||
|
||||
public virtual string ExecutableName { get; } = null!;
|
||||
|
||||
public virtual string Directory { get; } = null!;
|
||||
|
||||
public string LockFilePath => Path.Combine(Directory, "Bloxstrap.lock");
|
||||
|
||||
public string ExecutablePath => Path.Combine(Directory, ExecutableName);
|
||||
|
||||
public virtual IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; }
|
||||
|
||||
|
||||
public CommonAppData()
|
||||
{
|
||||
if (PackageDirectoryMap is null)
|
||||
|
@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bloxstrap.AppData
|
||||
namespace Bloxstrap.AppData
|
||||
{
|
||||
internal interface IAppData
|
||||
{
|
||||
@ -18,6 +12,14 @@ namespace Bloxstrap.AppData
|
||||
|
||||
string StartEvent { get; }
|
||||
|
||||
string Directory { get; }
|
||||
|
||||
string LockFilePath { get; }
|
||||
|
||||
string ExecutablePath { get; }
|
||||
|
||||
AppState State { get; }
|
||||
|
||||
IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,19 @@ namespace Bloxstrap.AppData
|
||||
{
|
||||
public class RobloxPlayerData : CommonAppData, IAppData
|
||||
{
|
||||
public string ProductName { get; } = "Roblox";
|
||||
public string ProductName => "Roblox";
|
||||
|
||||
public string BinaryType { get; } = "WindowsPlayer";
|
||||
public string BinaryType => "WindowsPlayer";
|
||||
|
||||
public string RegistryName { get; } = "RobloxPlayer";
|
||||
public string RegistryName => "RobloxPlayer";
|
||||
|
||||
public string ExecutableName { get; } = "RobloxPlayerBeta.exe";
|
||||
public override string ExecutableName => "RobloxPlayerBeta.exe";
|
||||
|
||||
public string StartEvent { get; } = "www.roblox.com/robloxStartedEvent";
|
||||
public string StartEvent => "www.roblox.com/robloxStartedEvent";
|
||||
|
||||
public override string Directory => Path.Combine(Paths.Roblox, "Player");
|
||||
|
||||
public AppState State => App.State.Prop.Player;
|
||||
|
||||
public override IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; } = new Dictionary<string, string>()
|
||||
{
|
||||
|
@ -1,22 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bloxstrap.AppData
|
||||
namespace Bloxstrap.AppData
|
||||
{
|
||||
public class RobloxStudioData : CommonAppData, IAppData
|
||||
{
|
||||
public string ProductName { get; } = "Roblox Studio";
|
||||
public string ProductName => "Roblox Studio";
|
||||
|
||||
public string BinaryType { get; } = "WindowsStudio64";
|
||||
public string BinaryType => "WindowsStudio64";
|
||||
|
||||
public string RegistryName { get; } = "RobloxStudio";
|
||||
public string RegistryName => "RobloxStudio";
|
||||
|
||||
public string ExecutableName { get; } = "RobloxStudioBeta.exe";
|
||||
public override string ExecutableName => "RobloxStudioBeta.exe";
|
||||
|
||||
public string StartEvent { get; } = "www.roblox.com/robloxStudioStartedEvent";
|
||||
public string StartEvent => "www.roblox.com/robloxStudioStartedEvent";
|
||||
|
||||
public override string Directory => Path.Combine(Paths.Roblox, "Studio");
|
||||
|
||||
public AppState State => App.State.Prop.Studio;
|
||||
|
||||
public override IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; } = new Dictionary<string, string>()
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bloxstrap.Exceptions
|
||||
{
|
||||
internal class HttpResponseException : Exception
|
||||
{
|
||||
public HttpResponseMessage ResponseMessage { get; }
|
||||
|
||||
public HttpResponseException(HttpResponseMessage responseMessage)
|
||||
: base($"Could not connect to {responseMessage.RequestMessage!.RequestUri} because it returned HTTP {(int)responseMessage.StatusCode} ({responseMessage.ReasonPhrase})")
|
||||
{
|
||||
ResponseMessage = responseMessage;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,15 +9,10 @@ namespace Bloxstrap.Extensions
|
||||
if (dialogTheme != Theme.Default)
|
||||
return dialogTheme;
|
||||
|
||||
RegistryKey? key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
|
||||
using var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
|
||||
|
||||
if (key is not null)
|
||||
{
|
||||
var value = key.GetValue("AppsUseLightTheme");
|
||||
|
||||
if (value is not null && (int)value == 0)
|
||||
return Theme.Dark;
|
||||
}
|
||||
if (key?.GetValue("AppsUseLightTheme") is int value && value == 0)
|
||||
return Theme.Dark;
|
||||
|
||||
return Theme.Light;
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ namespace Bloxstrap
|
||||
{ "UI.FlagState", "FStringDebugShowFlagState" },
|
||||
#endif
|
||||
|
||||
{ "UI.Menu.GraphicsSlider", "FFlagFixGraphicsQuality" },
|
||||
{ "UI.FullscreenTitlebarDelay", "FIntFullscreenTitleBarTriggerDelayMillis" },
|
||||
|
||||
{ "UI.Menu.Style.V2Rollout", "FIntNewInGameMenuPercentRollout3" },
|
||||
@ -62,7 +61,6 @@ namespace Bloxstrap
|
||||
{ "UI.Menu.Style.ABTest.3", "FFlagEnableInGameMenuChromeABTest3" }
|
||||
};
|
||||
|
||||
// only one missing here is Metal because lol
|
||||
public static IReadOnlyDictionary<RenderingMode, string> RenderingModes => new Dictionary<RenderingMode, string>
|
||||
{
|
||||
{ RenderingMode.Default, "None" },
|
||||
|
@ -2,8 +2,6 @@
|
||||
{
|
||||
public static class GlobalCache
|
||||
{
|
||||
public static readonly Dictionary<string, Task> PendingTasks = new();
|
||||
|
||||
public static readonly Dictionary<string, string> ServerLocation = new();
|
||||
public static readonly Dictionary<string, string?> ServerLocation = new();
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ global using System.Collections.Generic;
|
||||
global using System.Diagnostics;
|
||||
global using System.Globalization;
|
||||
global using System.IO;
|
||||
global using System.IO.Compression;
|
||||
global using System.Text;
|
||||
global using System.Text.Json;
|
||||
global using System.Text.Json.Serialization;
|
||||
@ -18,10 +17,16 @@ global using Bloxstrap.Enums;
|
||||
global using Bloxstrap.Exceptions;
|
||||
global using Bloxstrap.Extensions;
|
||||
global using Bloxstrap.Models;
|
||||
global using Bloxstrap.Models.APIs.Config;
|
||||
global using Bloxstrap.Models.APIs.GitHub;
|
||||
global using Bloxstrap.Models.APIs.Roblox;
|
||||
global using Bloxstrap.Models.Attributes;
|
||||
global using Bloxstrap.Models.BloxstrapRPC;
|
||||
global using Bloxstrap.Models.RobloxApi;
|
||||
global using Bloxstrap.Models.Entities;
|
||||
global using Bloxstrap.Models.Manifest;
|
||||
global using Bloxstrap.Models.Persistable;
|
||||
global using Bloxstrap.Models.SettingTasks;
|
||||
global using Bloxstrap.Models.SettingTasks.Base;
|
||||
global using Bloxstrap.Resources;
|
||||
global using Bloxstrap.UI;
|
||||
global using Bloxstrap.Utility;
|
@ -35,7 +35,19 @@ namespace Bloxstrap
|
||||
if (!IsImplicitInstall)
|
||||
{
|
||||
Filesystem.AssertReadOnly(Paths.Application);
|
||||
File.Copy(Paths.Process, Paths.Application, true);
|
||||
|
||||
try
|
||||
{
|
||||
File.Copy(Paths.Process, Paths.Application, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, "Could not overwrite executable");
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
|
||||
Frontend.ShowMessageBox(Strings.Installer_Install_CannotOverwrite, MessageBoxImage.Error);
|
||||
App.Terminate(ErrorCode.ERROR_INSTALL_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: registry access checks, i'll need to look back on issues to see what the error looks like
|
||||
@ -63,10 +75,7 @@ namespace Bloxstrap
|
||||
// only register player, for the scenario where the user installs bloxstrap, closes it,
|
||||
// and then launches from the website expecting it to work
|
||||
// studio can be implicitly registered when it's first launched manually
|
||||
ProtocolHandler.Register("roblox", "Roblox", Paths.Application, "-player \"%1\"");
|
||||
ProtocolHandler.Register("roblox-player", "Roblox", Paths.Application, "-player \"%1\"");
|
||||
|
||||
// TODO: implicit installation needs to reregister studio
|
||||
WindowsRegistry.RegisterPlayer();
|
||||
|
||||
if (CreateDesktopShortcuts)
|
||||
Shortcut.Create(Paths.Application, "", DesktopShortcut);
|
||||
@ -79,6 +88,9 @@ namespace Bloxstrap
|
||||
App.State.Load(false);
|
||||
App.FastFlags.Load(false);
|
||||
|
||||
if (!String.IsNullOrEmpty(App.State.Prop.Studio.VersionGuid))
|
||||
WindowsRegistry.RegisterStudio();
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, "Installation finished");
|
||||
}
|
||||
|
||||
@ -92,6 +104,10 @@ namespace Bloxstrap
|
||||
if (InstallLocation.StartsWith("\\\\"))
|
||||
return false;
|
||||
|
||||
if (InstallLocation.StartsWith(Path.GetTempPath(), StringComparison.InvariantCultureIgnoreCase)
|
||||
|| InstallLocation.Contains("\\Temp\\", StringComparison.InvariantCultureIgnoreCase))
|
||||
return false;
|
||||
|
||||
// prevent from installing to a onedrive folder
|
||||
if (InstallLocation.Contains("OneDrive", StringComparison.InvariantCultureIgnoreCase))
|
||||
return false;
|
||||
@ -162,11 +178,12 @@ namespace Bloxstrap
|
||||
const string LOG_IDENT = "Installer::DoUninstall";
|
||||
|
||||
var processes = new List<Process>();
|
||||
processes.AddRange(Process.GetProcessesByName(App.RobloxPlayerAppName));
|
||||
|
||||
#if STUDIO_FEATURES
|
||||
processes.AddRange(Process.GetProcessesByName(App.RobloxStudioAppName));
|
||||
#endif
|
||||
if (!String.IsNullOrEmpty(App.State.Prop.Player.VersionGuid))
|
||||
processes.AddRange(Process.GetProcessesByName(App.RobloxPlayerAppName));
|
||||
|
||||
if (!String.IsNullOrEmpty(App.State.Prop.Studio.VersionGuid))
|
||||
processes.AddRange(Process.GetProcessesByName(App.RobloxStudioAppName));
|
||||
|
||||
// prompt to shutdown roblox if its currently running
|
||||
if (processes.Any())
|
||||
@ -179,7 +196,10 @@ namespace Bloxstrap
|
||||
);
|
||||
|
||||
if (result != MessageBoxResult.OK)
|
||||
{
|
||||
App.Terminate(ErrorCode.ERROR_CANCELLED);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@ -207,44 +227,38 @@ namespace Bloxstrap
|
||||
{
|
||||
playerStillInstalled = false;
|
||||
|
||||
ProtocolHandler.Unregister("roblox");
|
||||
ProtocolHandler.Unregister("roblox-player");
|
||||
WindowsRegistry.Unregister("roblox");
|
||||
WindowsRegistry.Unregister("roblox-player");
|
||||
}
|
||||
else
|
||||
{
|
||||
// revert launch uri handler to stock bootstrapper
|
||||
string playerPath = Path.Combine((string)playerFolder, "RobloxPlayerBeta.exe");
|
||||
|
||||
ProtocolHandler.Register("roblox", "Roblox", playerPath);
|
||||
ProtocolHandler.Register("roblox-player", "Roblox", playerPath);
|
||||
WindowsRegistry.RegisterPlayer(playerPath, "%1");
|
||||
}
|
||||
|
||||
using RegistryKey? studioBootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-studio");
|
||||
if (studioBootstrapperKey is null)
|
||||
using var studioKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-studio");
|
||||
var studioFolder = studioKey?.GetValue("InstallLocation");
|
||||
|
||||
if (studioKey is null || studioFolder is not string)
|
||||
{
|
||||
studioStillInstalled = false;
|
||||
|
||||
#if STUDIO_FEATURES
|
||||
ProtocolHandler.Unregister("roblox-studio");
|
||||
ProtocolHandler.Unregister("roblox-studio-auth");
|
||||
WindowsRegistry.Unregister("roblox-studio");
|
||||
WindowsRegistry.Unregister("roblox-studio-auth");
|
||||
|
||||
ProtocolHandler.Unregister("Roblox.Place");
|
||||
ProtocolHandler.Unregister(".rbxl");
|
||||
ProtocolHandler.Unregister(".rbxlx");
|
||||
#endif
|
||||
WindowsRegistry.Unregister("Roblox.Place");
|
||||
WindowsRegistry.Unregister(".rbxl");
|
||||
WindowsRegistry.Unregister(".rbxlx");
|
||||
}
|
||||
#if STUDIO_FEATURES
|
||||
else
|
||||
{
|
||||
string studioLocation = (string?)studioBootstrapperKey.GetValue("InstallLocation") + "RobloxStudioBeta.exe"; // points to studio exe instead of bootstrapper
|
||||
ProtocolHandler.Register("roblox-studio", "Roblox", studioLocation);
|
||||
ProtocolHandler.Register("roblox-studio-auth", "Roblox", studioLocation);
|
||||
string studioPath = Path.Combine((string)studioFolder, "RobloxStudioBeta.exe");
|
||||
string studioLauncherPath = Path.Combine((string)studioFolder, "RobloxStudioLauncherBeta.exe");
|
||||
|
||||
ProtocolHandler.RegisterRobloxPlace(studioLocation);
|
||||
WindowsRegistry.RegisterStudioProtocol(studioPath, "%1");
|
||||
WindowsRegistry.RegisterStudioFileClass(studioPath, "-ide \"%1\"");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
var cleanupSequence = new List<Action>
|
||||
{
|
||||
@ -261,8 +275,10 @@ namespace Bloxstrap
|
||||
|
||||
() => File.Delete(StartMenuShortcut),
|
||||
|
||||
() => Directory.Delete(Paths.Versions, true),
|
||||
() => Directory.Delete(Paths.Downloads, true),
|
||||
() => Directory.Delete(Paths.Roblox, true),
|
||||
|
||||
() => File.Delete(App.State.FileLocation)
|
||||
};
|
||||
|
||||
if (!keepData)
|
||||
@ -272,8 +288,7 @@ namespace Bloxstrap
|
||||
() => Directory.Delete(Paths.Modifications, true),
|
||||
() => Directory.Delete(Paths.Logs, true),
|
||||
|
||||
() => File.Delete(App.Settings.FileLocation),
|
||||
() => File.Delete(App.State.FileLocation), // TODO: maybe this should always be deleted? not sure yet
|
||||
() => File.Delete(App.Settings.FileLocation)
|
||||
});
|
||||
}
|
||||
|
||||
@ -383,15 +398,30 @@ namespace Bloxstrap
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
// prior to 2.8.0, auto-updating was handled with this... bruteforce method
|
||||
// now it's handled with the system mutex you see above, but we need to keep this logic for <2.8.0 versions
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
File.Copy(Paths.Process, Paths.Application, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, "Failed to update! (Could not replace executable)");
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
return;
|
||||
try
|
||||
{
|
||||
File.Copy(Paths.Process, Paths.Application, true);
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, "Waiting for write permissions to update version");
|
||||
}
|
||||
else if (i == 10)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, "Failed to update! (Could not get write permissions after 10 tries/5 seconds)");
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
return;
|
||||
}
|
||||
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
using (var uninstallKey = Registry.CurrentUser.CreateSubKey(App.UninstallKey))
|
||||
@ -512,8 +542,7 @@ namespace Bloxstrap
|
||||
|
||||
Registry.CurrentUser.DeleteSubKeyTree("Software\\Bloxstrap", false);
|
||||
|
||||
ProtocolHandler.Register("roblox", "Roblox", Paths.Application, "-player \"%1\"");
|
||||
ProtocolHandler.Register("roblox-player", "Roblox", Paths.Application, "-player \"%1\"");
|
||||
WindowsRegistry.RegisterPlayer();
|
||||
|
||||
string? oldV2Val = App.FastFlags.GetValue("FFlagDisableNewIGMinDUA");
|
||||
|
||||
@ -526,6 +555,10 @@ namespace Bloxstrap
|
||||
|
||||
App.FastFlags.SetValue("FFlagDisableNewIGMinDUA", null);
|
||||
}
|
||||
|
||||
App.FastFlags.SetValue("FFlagFixGraphicsQuality", null);
|
||||
|
||||
Directory.Delete(Path.Combine(Paths.Base, "Versions"));
|
||||
}
|
||||
|
||||
App.Settings.Save();
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace Bloxstrap.Integrations
|
||||
namespace Bloxstrap.Integrations
|
||||
{
|
||||
public class ActivityWatcher : IDisposable
|
||||
{
|
||||
@ -40,7 +38,6 @@ namespace Bloxstrap.Integrations
|
||||
public event EventHandler? OnAppClose;
|
||||
public event EventHandler<Message>? OnRPCMessage;
|
||||
|
||||
private readonly Dictionary<string, string> GeolocationCache = new();
|
||||
private DateTime LastRPCRequest;
|
||||
|
||||
public string LogLocation = null!;
|
||||
|
@ -60,7 +60,21 @@ namespace Bloxstrap
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Saving to {FileLocation}...");
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(FileLocation)!);
|
||||
File.WriteAllText(FileLocation, JsonSerializer.Serialize(Prop, new JsonSerializerOptions { WriteIndented = true }));
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllText(FileLocation, JsonSerializer.Serialize(Prop, new JsonSerializerOptions { WriteIndented = true }));
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, "Failed to save");
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
|
||||
string errorMessage = string.Format(Resources.Strings.Bootstrapper_JsonManagerSaveFailed, ClassName, ex.Message);
|
||||
Frontend.ShowMessageBox(errorMessage, System.Windows.MessageBoxImage.Warning);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, "Save complete!");
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System.Windows;
|
||||
|
||||
using Microsoft.Win32;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
@ -43,6 +42,8 @@ namespace Bloxstrap
|
||||
LaunchRoblox();
|
||||
else if (!App.LaunchSettings.QuietFlag.Active)
|
||||
LaunchMenu();
|
||||
else
|
||||
App.Terminate();
|
||||
}
|
||||
|
||||
public static void LaunchInstaller()
|
||||
@ -52,6 +53,7 @@ namespace Bloxstrap
|
||||
if (!interlock.IsAcquired)
|
||||
{
|
||||
Frontend.ShowMessageBox(Strings.Dialog_AlreadyRunning_Installer, MessageBoxImage.Stop);
|
||||
App.Terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -96,6 +98,7 @@ namespace Bloxstrap
|
||||
if (!interlock.IsAcquired)
|
||||
{
|
||||
Frontend.ShowMessageBox(Strings.Dialog_AlreadyRunning_Uninstaller, MessageBoxImage.Stop);
|
||||
App.Terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -116,7 +119,10 @@ namespace Bloxstrap
|
||||
}
|
||||
|
||||
if (!confirmed)
|
||||
{
|
||||
App.Terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
Installer.DoUninstall(keepData);
|
||||
|
||||
@ -134,7 +140,9 @@ namespace Bloxstrap
|
||||
if (interlock.IsAcquired)
|
||||
{
|
||||
bool showAlreadyRunningWarning = Process.GetProcessesByName(App.ProjectName).Length > 1;
|
||||
new UI.Elements.Settings.MainWindow(showAlreadyRunningWarning).Show();
|
||||
|
||||
var window = new UI.Elements.Settings.MainWindow(showAlreadyRunningWarning);
|
||||
window.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -169,15 +177,6 @@ namespace Bloxstrap
|
||||
App.Terminate(ErrorCode.ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
bool installWebView2 = false;
|
||||
{
|
||||
using var hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}");
|
||||
using var hkcuKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}");
|
||||
|
||||
if (hklmKey is null && hkcuKey is null)
|
||||
installWebView2 = Frontend.ShowMessageBox(Strings.Bootstrapper_WebView2NotFound, MessageBoxImage.Warning, MessageBoxButton.YesNo, MessageBoxResult.Yes) == MessageBoxResult.Yes;
|
||||
}
|
||||
|
||||
if (App.Settings.Prop.ConfirmLaunches && Mutex.TryOpenExisting("ROBLOX_singletonMutex", out var _))
|
||||
{
|
||||
// this currently doesn't work very well since it relies on checking the existence of the singleton mutex
|
||||
@ -195,7 +194,7 @@ namespace Bloxstrap
|
||||
|
||||
// start bootstrapper and show the bootstrapper modal if we're not running silently
|
||||
App.Logger.WriteLine(LOG_IDENT, "Initializing bootstrapper");
|
||||
var bootstrapper = new Bootstrapper(installWebView2);
|
||||
var bootstrapper = new Bootstrapper();
|
||||
IBootstrapperDialog? dialog = null;
|
||||
|
||||
if (!App.LaunchSettings.QuietFlag.Active)
|
||||
|
@ -28,7 +28,11 @@ namespace Bloxstrap
|
||||
|
||||
public LaunchFlag StudioFlag { get; } = new("studio");
|
||||
|
||||
#if DEBUG
|
||||
public bool BypassUpdateCheck => true;
|
||||
#else
|
||||
public bool BypassUpdateCheck => UninstallFlag.Active || WatcherFlag.Active;
|
||||
#endif
|
||||
|
||||
public LaunchMode RobloxLaunchMode { get; set; } = LaunchMode.None;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.APIs.Config
|
||||
{
|
||||
public class Supporter
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.APIs.Config
|
||||
{
|
||||
public class SupporterData
|
||||
{
|
8
Bloxstrap/Models/APIs/GitHub/GitHubReleaseAsset.cs
Normal file
8
Bloxstrap/Models/APIs/GitHub/GitHubReleaseAsset.cs
Normal file
@ -0,0 +1,8 @@
|
||||
public class GithubReleaseAsset
|
||||
{
|
||||
[JsonPropertyName("browser_download_url")]
|
||||
public string BrowserDownloadUrl { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = null!;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.APIs.GitHub
|
||||
{
|
||||
public class GithubRelease
|
||||
{
|
||||
@ -17,13 +17,4 @@
|
||||
[JsonPropertyName("assets")]
|
||||
public List<GithubReleaseAsset>? Assets { get; set; }
|
||||
}
|
||||
|
||||
public class GithubReleaseAsset
|
||||
{
|
||||
[JsonPropertyName("browser_download_url")]
|
||||
public string BrowserDownloadUrl { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = null!;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.APIs
|
||||
{
|
||||
public class IPInfoResponse
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models.RobloxApi
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
/// <summary>
|
||||
/// Roblox.Web.WebAPI.Models.ApiArrayResponse
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
public class ClientFlagSettings
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
public class ClientVersion
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models.RobloxApi
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
/// <summary>
|
||||
/// Roblox.Games.Api.Models.Response.GameCreator
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models.RobloxApi
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
|
||||
/// <summary>
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models.RobloxApi
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
/// <summary>
|
||||
/// Roblox.Web.Responses.Thumbnails.ThumbnailResponse
|
@ -1,4 +1,4 @@
|
||||
namespace Bloxstrap.Models.RobloxApi
|
||||
namespace Bloxstrap.Models.APIs.Roblox
|
||||
{
|
||||
// lmao its just one property
|
||||
public class UniverseIdResponse
|
@ -1,10 +1,10 @@
|
||||
using System.Web;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
using Bloxstrap.Models.APIs;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.Entities
|
||||
{
|
||||
public class ActivityData
|
||||
{
|
||||
@ -28,18 +28,18 @@ namespace Bloxstrap.Models
|
||||
|
||||
public long PlaceId { get; set; } = 0;
|
||||
|
||||
public string JobId { get; set; } = String.Empty;
|
||||
public string JobId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// This will be empty unless the server joined is a private server
|
||||
/// </summary>
|
||||
public string AccessCode { get; set; } = String.Empty;
|
||||
|
||||
public string MachineAddress { get; set; } = String.Empty;
|
||||
public string AccessCode { get; set; } = string.Empty;
|
||||
|
||||
public string UserId { get; set; } = String.Empty;
|
||||
|
||||
public bool MachineAddressValid => !String.IsNullOrEmpty(MachineAddress) && !MachineAddress.StartsWith("10.");
|
||||
public string MachineAddress { get; set; } = string.Empty;
|
||||
|
||||
public bool MachineAddressValid => !string.IsNullOrEmpty(MachineAddress) && !MachineAddress.StartsWith("10.");
|
||||
|
||||
public bool IsTeleport { get; set; } = false;
|
||||
|
||||
@ -54,7 +54,7 @@ namespace Bloxstrap.Models
|
||||
/// <summary>
|
||||
/// This is intended only for other people to use, i.e. context menu invite link, rich presence joining
|
||||
/// </summary>
|
||||
public string RPCLaunchData { get; set; } = String.Empty;
|
||||
public string RPCLaunchData { get; set; } = string.Empty;
|
||||
|
||||
public UniverseDetails? UniverseDetails { get; set; }
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Bloxstrap.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
string desc = String.Format("{0} • {1} - {2}", UniverseDetails?.Data.Creator.Name, TimeJoined.ToString("h:mm tt"), TimeLeft?.ToString("h:mm tt"));
|
||||
string desc = string.Format("{0} • {1} - {2}", UniverseDetails?.Data.Creator.Name, TimeJoined.ToString("h:mm tt"), TimeLeft?.ToString("h:mm tt"));
|
||||
|
||||
if (ServerType != ServerType.Public)
|
||||
desc += " • " + ServerType.ToTranslatedString();
|
||||
@ -73,6 +73,8 @@ namespace Bloxstrap.Models
|
||||
|
||||
public ICommand RejoinServerCommand => new RelayCommand(RejoinServer);
|
||||
|
||||
private SemaphoreSlim serverQuerySemaphore = new(1, 1);
|
||||
|
||||
public string GetInviteDeeplink(bool launchData = true)
|
||||
{
|
||||
string deeplink = $"roblox://experiences/start?placeId={PlaceId}";
|
||||
@ -82,37 +84,32 @@ namespace Bloxstrap.Models
|
||||
else
|
||||
deeplink += "&gameInstanceId=" + JobId;
|
||||
|
||||
if (launchData && !String.IsNullOrEmpty(RPCLaunchData))
|
||||
if (launchData && !string.IsNullOrEmpty(RPCLaunchData))
|
||||
deeplink += "&launchData=" + HttpUtility.UrlEncode(RPCLaunchData);
|
||||
|
||||
return deeplink;
|
||||
}
|
||||
|
||||
public async Task<string> QueryServerLocation()
|
||||
public async Task<string?> QueryServerLocation()
|
||||
{
|
||||
const string LOG_IDENT = "ActivityData::QueryServerLocation";
|
||||
|
||||
if (!MachineAddressValid)
|
||||
throw new InvalidOperationException($"Machine address is invalid ({MachineAddress})");
|
||||
|
||||
if (GlobalCache.PendingTasks.TryGetValue(MachineAddress, out Task? task))
|
||||
await task;
|
||||
await serverQuerySemaphore.WaitAsync();
|
||||
|
||||
if (GlobalCache.ServerLocation.TryGetValue(MachineAddress, out string? location))
|
||||
{
|
||||
serverQuerySemaphore.Release();
|
||||
return location;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
location = "";
|
||||
var ipInfoTask = Http.GetJson<IPInfoResponse>($"https://ipinfo.io/{MachineAddress}/json");
|
||||
var ipInfo = await Http.GetJson<IPInfoResponse>($"https://ipinfo.io/{MachineAddress}/json");
|
||||
|
||||
GlobalCache.PendingTasks.Add(MachineAddress, ipInfoTask);
|
||||
|
||||
var ipInfo = await ipInfoTask;
|
||||
|
||||
GlobalCache.PendingTasks.Remove(MachineAddress);
|
||||
|
||||
if (String.IsNullOrEmpty(ipInfo.City))
|
||||
if (string.IsNullOrEmpty(ipInfo.City))
|
||||
throw new InvalidHTTPResponseException("Reported city was blank");
|
||||
|
||||
if (ipInfo.City == ipInfo.Region)
|
||||
@ -121,25 +118,32 @@ namespace Bloxstrap.Models
|
||||
location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}";
|
||||
|
||||
GlobalCache.ServerLocation[MachineAddress] = location;
|
||||
|
||||
return location;
|
||||
serverQuerySemaphore.Release();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {MachineAddress}");
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
|
||||
Frontend.ShowMessageBox($"{Strings.ActivityWatcher_LocationQueryFailed}\n\n{ex.Message}", MessageBoxImage.Warning);
|
||||
GlobalCache.ServerLocation[MachineAddress] = location;
|
||||
serverQuerySemaphore.Release();
|
||||
|
||||
return "?";
|
||||
Frontend.ShowConnectivityDialog(
|
||||
string.Format(Strings.Dialog_Connectivity_UnableToConnect, "ipinfo.io"),
|
||||
Strings.ActivityWatcher_LocationQueryFailed,
|
||||
MessageBoxImage.Warning,
|
||||
ex
|
||||
);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{PlaceId}/{JobId}";
|
||||
|
||||
private void RejoinServer()
|
||||
{
|
||||
string playerPath = Path.Combine(Paths.Versions, App.State.Prop.PlayerVersionGuid, "RobloxPlayerBeta.exe");
|
||||
string playerPath = Path.Combine(Paths.Roblox, "Player", "RobloxPlayerBeta.exe");
|
||||
|
||||
Process.Start(playerPath, GetInviteDeeplink(false));
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.Entities
|
||||
{
|
||||
public class ModPresetFileData
|
||||
{
|
@ -1,4 +1,6 @@
|
||||
namespace Bloxstrap.Models
|
||||
using Bloxstrap.Models.APIs.Roblox;
|
||||
|
||||
namespace Bloxstrap.Models.Entities
|
||||
{
|
||||
public class UniverseDetails
|
||||
{
|
||||
@ -13,9 +15,9 @@
|
||||
|
||||
public static UniverseDetails? LoadFromCache(long id)
|
||||
{
|
||||
var cacheQuery = _cache.Where(x => x.Data?.Id == id);
|
||||
var cacheQuery = _cache.Where(x => x.Data?.Id == id);
|
||||
|
||||
if (cacheQuery.Any())
|
||||
if (cacheQuery.Any())
|
||||
return cacheQuery.First();
|
||||
|
||||
return null;
|
@ -9,10 +9,15 @@ namespace Bloxstrap.Models.Manifest
|
||||
public class Package
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public string Signature { get; set; } = "";
|
||||
|
||||
public int PackedSize { get; set; }
|
||||
|
||||
public int Size { get; set; }
|
||||
|
||||
public string DownloadPath => Path.Combine(Paths.Downloads, Signature);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{Signature}] {Name}";
|
||||
|
@ -8,9 +8,9 @@ namespace Bloxstrap.Models.Manifest
|
||||
{
|
||||
public class PackageManifest : List<Package>
|
||||
{
|
||||
private PackageManifest(string data)
|
||||
public PackageManifest(string data)
|
||||
{
|
||||
using StringReader reader = new StringReader(data);
|
||||
using var reader = new StringReader(data);
|
||||
string? version = reader.ReadLine();
|
||||
|
||||
if (version != "v0")
|
||||
@ -46,13 +46,5 @@ namespace Bloxstrap.Models.Manifest
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<PackageManifest> Get(string versionGuid)
|
||||
{
|
||||
string pkgManifestUrl = RobloxDeployment.GetLocation($"/{versionGuid}-rbxPkgManifest.txt");
|
||||
var pkgManifestData = await App.HttpClient.GetStringAsync(pkgManifestUrl);
|
||||
|
||||
return new PackageManifest(pkgManifestData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Bloxstrap/Models/Persistable/AppState.cs
Normal file
11
Bloxstrap/Models/Persistable/AppState.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Bloxstrap.Models.Persistable
|
||||
{
|
||||
public class AppState
|
||||
{
|
||||
public string VersionGuid { get; set; } = string.Empty;
|
||||
|
||||
public Dictionary<string, string> PackageHashes { get; set; } = new();
|
||||
|
||||
public int Size { get; set; }
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Bloxstrap.Models
|
||||
namespace Bloxstrap.Models.Persistable
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
@ -26,6 +26,5 @@ namespace Bloxstrap.Models
|
||||
|
||||
// mod preset configuration
|
||||
public bool UseDisableAppPatch { get; set; } = false;
|
||||
public bool DisableFullscreenOptimizations { get; set; } = false;
|
||||
}
|
||||
}
|
17
Bloxstrap/Models/Persistable/State.cs
Normal file
17
Bloxstrap/Models/Persistable/State.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Bloxstrap.Models.Persistable
|
||||
{
|
||||
public class State
|
||||
{
|
||||
public bool ShowFFlagEditorWarning { get; set; } = true;
|
||||
|
||||
public bool PromptWebView2Install { get; set; } = true;
|
||||
|
||||
public AppState Player { get; set; } = new();
|
||||
|
||||
public AppState Studio { get; set; } = new();
|
||||
|
||||
public WindowState SettingsWindow { get; set; } = new();
|
||||
|
||||
public List<string> ModManifest { get; set; } = new();
|
||||
}
|
||||
}
|
13
Bloxstrap/Models/Persistable/WindowState.cs
Normal file
13
Bloxstrap/Models/Persistable/WindowState.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Bloxstrap.Models.Persistable
|
||||
{
|
||||
public class WindowState
|
||||
{
|
||||
public double Width { get; set; }
|
||||
|
||||
public double Height { get; set; }
|
||||
|
||||
public double Left { get; set; }
|
||||
|
||||
public double Top { get; set; }
|
||||
}
|
||||
}
|
@ -52,9 +52,12 @@ namespace Bloxstrap.Models.SettingTasks
|
||||
{
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
|
||||
Frontend.ShowMessageBox(
|
||||
String.Format(Strings.Menu_Mods_Presets_EmojiType_Error, ex.Message),
|
||||
MessageBoxImage.Warning);
|
||||
Frontend.ShowConnectivityDialog(
|
||||
String.Format(Strings.Dialog_Connectivity_UnableToConnect, "GitHub"),
|
||||
$"{Strings.Menu_Mods_Presets_EmojiType_Error}\n\n{Strings.Dialog_Connectivity_TryAgainLater}",
|
||||
MessageBoxImage.Warning,
|
||||
ex
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (query is not null && query.Any())
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bloxstrap.Models.SettingTasks.Base;
|
||||
using Bloxstrap.Models.Entities;
|
||||
using Bloxstrap.Models.SettingTasks.Base;
|
||||
|
||||
namespace Bloxstrap.Models.SettingTasks
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bloxstrap.Models.SettingTasks.Base;
|
||||
using Bloxstrap.Models.Entities;
|
||||
using Bloxstrap.Models.SettingTasks.Base;
|
||||
|
||||
namespace Bloxstrap.Models.SettingTasks
|
||||
{
|
||||
|
@ -1,17 +0,0 @@
|
||||
namespace Bloxstrap.Models
|
||||
{
|
||||
public class State
|
||||
{
|
||||
public bool ShowFFlagEditorWarning { get; set; } = true;
|
||||
|
||||
[Obsolete("Use PlayerVersionGuid instead", true)]
|
||||
public string VersionGuid { set { PlayerVersionGuid = value; } }
|
||||
public string PlayerVersionGuid { get; set; } = "";
|
||||
public string StudioVersionGuid { get; set; } = "";
|
||||
|
||||
public int PlayerSize { get; set; } = 0;
|
||||
public int StudioSize { get; set; } = 0;
|
||||
|
||||
public List<string> ModManifest { get; set; } = new();
|
||||
}
|
||||
}
|
@ -2,4 +2,4 @@
|
||||
FlashWindow
|
||||
GetWindowLong
|
||||
SetWindowLong
|
||||
EnumDisplaySettings
|
||||
SHObjectProperties
|
@ -20,8 +20,8 @@
|
||||
public static string Downloads { get; private set; } = "";
|
||||
public static string Logs { get; private set; } = "";
|
||||
public static string Integrations { get; private set; } = "";
|
||||
public static string Versions { get; private set; } = "";
|
||||
public static string Modifications { get; private set; } = "";
|
||||
public static string Roblox { get; private set; } = "";
|
||||
|
||||
public static string Application { get; private set; } = "";
|
||||
|
||||
@ -35,8 +35,8 @@
|
||||
Downloads = Path.Combine(Base, "Downloads");
|
||||
Logs = Path.Combine(Base, "Logs");
|
||||
Integrations = Path.Combine(Base, "Integrations");
|
||||
Versions = Path.Combine(Base, "Versions");
|
||||
Modifications = Path.Combine(Base, "Modifications");
|
||||
Roblox = Path.Combine(Base, "Roblox");
|
||||
|
||||
Application = Path.Combine(Base, $"{App.ProjectName}.exe");
|
||||
}
|
||||
|
181
Bloxstrap/Resources/Strings.Designer.cs
generated
181
Bloxstrap/Resources/Strings.Designer.cs
generated
@ -106,7 +106,7 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Failed to query server location..
|
||||
/// Looks up a localized string similar to The server location could not be queried. You may be joining games too quickly..
|
||||
/// </summary>
|
||||
public static string ActivityWatcher_LocationQueryFailed {
|
||||
get {
|
||||
@ -141,33 +141,6 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to It's possible that something is preventing Bloxstrap from connecting to the internet. Please check and try again..
|
||||
/// </summary>
|
||||
public static string Bootstrapper_Connectivity_Preventing {
|
||||
get {
|
||||
return ResourceManager.GetString("Bootstrapper.Connectivity.Preventing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Roblox may be down right now. See status.roblox.com for more information. Please try again later..
|
||||
/// </summary>
|
||||
public static string Bootstrapper_Connectivity_RobloxDown {
|
||||
get {
|
||||
return ResourceManager.GetString("Bootstrapper.Connectivity.RobloxDown", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bloxstrap timed out when trying to connect to three different Roblox deployment mirrors, indicating a poor internet connection. Please try again later..
|
||||
/// </summary>
|
||||
public static string Bootstrapper_Connectivity_TimedOut {
|
||||
get {
|
||||
return ResourceManager.GetString("Bootstrapper.Connectivity.TimedOut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Could not apply the {0} emoji mod preset because of a network error. To try again, please reconfigure the option in the Bloxstrap Menu..
|
||||
/// </summary>
|
||||
@ -197,6 +170,15 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Failed to save {0}: {1}.
|
||||
/// </summary>
|
||||
public static string Bootstrapper_JsonManagerSaveFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("Bootstrapper.JsonManagerSaveFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bloxstrap does not have enough disk space to download and install Roblox. Please free up some disk space and try again..
|
||||
/// </summary>
|
||||
@ -539,6 +521,15 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not available.
|
||||
/// </summary>
|
||||
public static string Common_NotAvailable {
|
||||
get {
|
||||
return ResourceManager.GetString("Common.NotAvailable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK.
|
||||
/// </summary>
|
||||
@ -575,6 +566,15 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Roblox has not yet been installed. Please launch Roblox using Bloxstrap at least once before trying to use this option..
|
||||
/// </summary>
|
||||
public static string Common_RobloxNotInstalled {
|
||||
get {
|
||||
return ResourceManager.GetString("Common.RobloxNotInstalled", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shortcuts.
|
||||
/// </summary>
|
||||
@ -828,6 +828,60 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Something is likely preventing Bloxstrap from connecting to the internet..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_Preventing {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.Preventing", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Roblox may be down right now. See {0} for more information..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_RobloxDown {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.RobloxDown", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Because Roblox needs to be installed or upgraded, Bloxstrap cannot continue..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_RobloxUpgradeNeeded {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.RobloxUpgradeNeeded", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to For this launch, Roblox will not be checked for upgrades, and changes to mods will not be applied..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_RobloxUpgradeSkip {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.RobloxUpgradeSkip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} may be down right now..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_ServiceDown {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.ServiceDown", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The connection timed out, which could indicate a poor internet connection or a firewall block..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_TimedOut {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.TimedOut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connectivity error.
|
||||
/// </summary>
|
||||
@ -838,7 +892,16 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bloxstrap is unable to connect to Roblox.
|
||||
/// Looks up a localized string similar to Please try again later..
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_TryAgainLater {
|
||||
get {
|
||||
return ResourceManager.GetString("Dialog.Connectivity.TryAgainLater", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bloxstrap is unable to connect to {0}.
|
||||
/// </summary>
|
||||
public static string Dialog_Connectivity_UnableToConnect {
|
||||
get {
|
||||
@ -1410,6 +1473,17 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bloxstrap has been installed to this location before and is still present, however the installer cannot overwrite the old executable.
|
||||
///
|
||||
///Please manually delete Bloxstrap.exe from the install location or try restarting your system, and then retry installation afterwards..
|
||||
/// </summary>
|
||||
public static string Installer_Install_CannotOverwrite {
|
||||
get {
|
||||
return ResourceManager.GetString("Installer.Install.CannotOverwrite", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Existing data found. Your mods and settings will be restored..
|
||||
/// </summary>
|
||||
@ -1455,6 +1529,15 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Are you sure you want to cancel the installation?.
|
||||
/// </summary>
|
||||
public static string Installer_ShouldCancel {
|
||||
get {
|
||||
return ResourceManager.GetString("Installer.ShouldCancel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bloxstrap Installer.
|
||||
/// </summary>
|
||||
@ -2270,24 +2353,6 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Allows you to configure 21 different quality levels instead of 10..
|
||||
/// </summary>
|
||||
public static string Menu_FastFlags_Presets_AltGraphicsSelector_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Menu.FastFlags.Presets.AltGraphicsSelector.Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Use advanced graphics quality selector.
|
||||
/// </summary>
|
||||
public static string Menu_FastFlags_Presets_AltGraphicsSelector_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Menu.FastFlags.Presets.AltGraphicsSelector.Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Rendering and Graphics.
|
||||
/// </summary>
|
||||
@ -2789,6 +2854,24 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Configure application parameters such as DPI scaling behaviour and [fullscreen optimizations]({0})..
|
||||
/// </summary>
|
||||
public static string Menu_Mods_Misc_CompatibilitySettings_Description {
|
||||
get {
|
||||
return ResourceManager.GetString("Menu.Mods.Misc.CompatibilitySettings.Description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Manage compatibility settings.
|
||||
/// </summary>
|
||||
public static string Menu_Mods_Misc_CompatibilitySettings_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Menu.Mods.Misc.CompatibilitySettings.Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Choose font....
|
||||
/// </summary>
|
||||
@ -2880,9 +2963,7 @@ namespace Bloxstrap.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The emoji mod could not be applied because of a network error during download.
|
||||
///
|
||||
///{0}.
|
||||
/// Looks up a localized string similar to The emoji mod can not be applied at this time..
|
||||
/// </summary>
|
||||
public static string Menu_Mods_Presets_EmojiType_Error {
|
||||
get {
|
||||
|
@ -123,14 +123,14 @@
|
||||
<data name="Bootstrapper.ConfirmLaunch" xml:space="preserve">
|
||||
<value>Roblox is currently running, and launching another instance will close it. Are you sure you want to continue launching?</value>
|
||||
</data>
|
||||
<data name="Bootstrapper.Connectivity.Preventing" xml:space="preserve">
|
||||
<value>It's possible that something is preventing Bloxstrap from connecting to the internet. Please check and try again.</value>
|
||||
<data name="Dialog.Connectivity.Preventing" xml:space="preserve">
|
||||
<value>Something is likely preventing Bloxstrap from connecting to the internet.</value>
|
||||
</data>
|
||||
<data name="Bootstrapper.Connectivity.RobloxDown" xml:space="preserve">
|
||||
<value>Roblox may be down right now. See status.roblox.com for more information. Please try again later.</value>
|
||||
<data name="Dialog.Connectivity.RobloxDown" xml:space="preserve">
|
||||
<value>Roblox may be down right now. See {0} for more information.</value>
|
||||
</data>
|
||||
<data name="Bootstrapper.Connectivity.TimedOut" xml:space="preserve">
|
||||
<value>Bloxstrap timed out when trying to connect to three different Roblox deployment mirrors, indicating a poor internet connection. Please try again later.</value>
|
||||
<data name="Dialog.Connectivity.TimedOut" xml:space="preserve">
|
||||
<value>The connection timed out, which could indicate a poor internet connection or a firewall block.</value>
|
||||
</data>
|
||||
<data name="Bootstrapper.EmojiPresetFetchFailed" xml:space="preserve">
|
||||
<value>Could not apply the {0} emoji mod preset because of a network error. To try again, please reconfigure the option in the Bloxstrap Menu.</value>
|
||||
@ -294,7 +294,7 @@ Click for more information</value>
|
||||
<value>Connectivity error</value>
|
||||
</data>
|
||||
<data name="Dialog.Connectivity.UnableToConnect" xml:space="preserve">
|
||||
<value>Bloxstrap is unable to connect to Roblox</value>
|
||||
<value>Bloxstrap is unable to connect to {0}</value>
|
||||
</data>
|
||||
<data name="Dialog.Exception.CopyLogContents" xml:space="preserve">
|
||||
<value>Copy log contents</value>
|
||||
@ -637,12 +637,6 @@ Do NOT use this to import large "flag lists" made by other people that promise t
|
||||
<value>Learn more about Fast Flags, what these presets do, and how to use them.</value>
|
||||
<comment>Title is Common.Help</comment>
|
||||
</data>
|
||||
<data name="Menu.FastFlags.Presets.AltGraphicsSelector.Description" xml:space="preserve">
|
||||
<value>Allows you to configure 21 different quality levels instead of 10.</value>
|
||||
</data>
|
||||
<data name="Menu.FastFlags.Presets.AltGraphicsSelector.Title" xml:space="preserve">
|
||||
<value>Use advanced graphics quality selector</value>
|
||||
</data>
|
||||
<data name="Menu.FastFlags.Presets.D3DExclusiveFullscreenInfo" xml:space="preserve">
|
||||
<value>Direct3D [exclusive fullscreen]({0}) using Alt+Enter is enabled by default.</value>
|
||||
</data>
|
||||
@ -1108,9 +1102,7 @@ If not, then please report this exception to the maintainers of this fork. Do NO
|
||||
<value>Connected to reserved server</value>
|
||||
</data>
|
||||
<data name="Menu.Mods.Presets.EmojiType.Error" xml:space="preserve">
|
||||
<value>The emoji mod could not be applied because of a network error during download.
|
||||
|
||||
{0}</value>
|
||||
<value>The emoji mod can not be applied at this time.</value>
|
||||
</data>
|
||||
<data name="Dialog.AlreadyRunning.Installer" xml:space="preserve">
|
||||
<value>Please wait for installation to finish.</value>
|
||||
@ -1175,6 +1167,41 @@ Are you sure you want to continue?</value>
|
||||
<value>Game history is only recorded for your current Roblox session. Games will appear here as you leave them or teleport within them.</value>
|
||||
</data>
|
||||
<data name="ActivityWatcher.LocationQueryFailed" xml:space="preserve">
|
||||
<value>Failed to query server location.</value>
|
||||
<value>The server location could not be queried. You may be joining games too quickly.</value>
|
||||
</data>
|
||||
<data name="Dialog.Connectivity.ServiceDown" xml:space="preserve">
|
||||
<value>{0} may be down right now.</value>
|
||||
</data>
|
||||
<data name="Dialog.Connectivity.TryAgainLater" xml:space="preserve">
|
||||
<value>Please try again later.</value>
|
||||
</data>
|
||||
<data name="Dialog.Connectivity.RobloxUpgradeSkip" xml:space="preserve">
|
||||
<value>For this launch, Roblox will not be checked for upgrades, and changes to mods will not be applied.</value>
|
||||
</data>
|
||||
<data name="Dialog.Connectivity.RobloxUpgradeNeeded" xml:space="preserve">
|
||||
<value>Because Roblox needs to be installed or upgraded, Bloxstrap cannot continue.</value>
|
||||
</data>
|
||||
<data name="Installer.Install.CannotOverwrite" xml:space="preserve">
|
||||
<value>Bloxstrap has been installed to this location before and is still present, however the installer cannot overwrite the old executable.
|
||||
|
||||
Please manually delete Bloxstrap.exe from the install location or try restarting your system, and then retry installation afterwards.</value>
|
||||
</data>
|
||||
<data name="Common.NotAvailable" xml:space="preserve">
|
||||
<value>Not available</value>
|
||||
</data>
|
||||
<data name="Menu.Mods.Misc.CompatibilitySettings.Title" xml:space="preserve">
|
||||
<value>Manage compatibility settings</value>
|
||||
</data>
|
||||
<data name="Menu.Mods.Misc.CompatibilitySettings.Description" xml:space="preserve">
|
||||
<value>Configure application parameters such as DPI scaling behaviour and [fullscreen optimizations]({0}).</value>
|
||||
</data>
|
||||
<data name="Common.RobloxNotInstalled" xml:space="preserve">
|
||||
<value>Roblox has not yet been installed. Please launch Roblox using Bloxstrap at least once before trying to use this option.</value>
|
||||
</data>
|
||||
<data name="Installer.ShouldCancel" xml:space="preserve">
|
||||
<value>Are you sure you want to cancel the installation?</value>
|
||||
</data>
|
||||
<data name="Bootstrapper.JsonManagerSaveFailed" xml:space="preserve">
|
||||
<value>Failed to save {0}: {1}</value>
|
||||
</data>
|
||||
</root>
|
||||
|
@ -15,6 +15,7 @@
|
||||
private static readonly Dictionary<string, int> BaseUrls = new()
|
||||
{
|
||||
{ "https://setup.rbxcdn.com", 0 },
|
||||
{ "https://setup-aws.rbxcdn.com", 2 },
|
||||
{ "https://setup-ak.rbxcdn.com", 2 },
|
||||
{ "https://roblox-setup.cachefly.net", 2 },
|
||||
{ "https://s3.amazonaws.com/setup.roblox.com", 4 }
|
||||
@ -22,7 +23,7 @@
|
||||
|
||||
private static async Task<string?> TestConnection(string url, int priority, CancellationToken token)
|
||||
{
|
||||
string LOG_IDENT = $"RobloxDeployment::TestConnection.{url}";
|
||||
string LOG_IDENT = $"RobloxDeployment::TestConnection<{url}>";
|
||||
|
||||
await Task.Delay(priority * 1000, token);
|
||||
|
||||
@ -32,14 +33,14 @@
|
||||
{
|
||||
var response = await App.HttpClient.GetAsync($"{url}/versionStudio", token);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new HttpResponseException(response);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// versionStudio is the version hash for the last MFC studio to be deployed.
|
||||
// the response body should always be "version-012732894899482c".
|
||||
string content = await response.Content.ReadAsStringAsync(token);
|
||||
|
||||
if (content != VersionStudioHash)
|
||||
throw new Exception($"versionStudio response does not match (expected \"{VersionStudioHash}\", got \"{content}\")");
|
||||
throw new InvalidHTTPResponseException($"versionStudio response does not match (expected \"{VersionStudioHash}\", got \"{content}\")");
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
@ -66,11 +67,10 @@
|
||||
|
||||
// returns null for success
|
||||
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||
CancellationToken token = tokenSource.Token;
|
||||
var tokenSource = new CancellationTokenSource();
|
||||
|
||||
var exceptions = new List<Exception>();
|
||||
var tasks = (from entry in BaseUrls select TestConnection(entry.Key, entry.Value, token)).ToList();
|
||||
var tasks = (from entry in BaseUrls select TestConnection(entry.Key, entry.Value, tokenSource.Token)).ToList();
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, "Testing connectivity...");
|
||||
|
||||
@ -127,7 +127,11 @@
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT, $"Getting deploy info for channel {channel}");
|
||||
|
||||
if (String.IsNullOrEmpty(channel))
|
||||
channel = DefaultChannel;
|
||||
|
||||
string cacheKey = $"{channel}-{binaryType}";
|
||||
|
||||
ClientVersion clientVersion;
|
||||
|
||||
if (ClientVersionCache.ContainsKey(cacheKey))
|
||||
@ -137,57 +141,37 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isDefaultChannel = String.Compare(channel, DefaultChannel, StringComparison.OrdinalIgnoreCase) == 0;
|
||||
|
||||
string path = $"/v2/client-version/{binaryType}";
|
||||
|
||||
if (String.Compare(channel, DefaultChannel, StringComparison.InvariantCultureIgnoreCase) != 0)
|
||||
if (!isDefaultChannel)
|
||||
path = $"/v2/client-version/{binaryType}/channel/{channel}";
|
||||
|
||||
HttpResponseMessage deployInfoResponse;
|
||||
|
||||
try
|
||||
{
|
||||
deployInfoResponse = await App.HttpClient.GetAsync("https://clientsettingscdn.roblox.com" + path);
|
||||
clientVersion = await Http.GetJson<ClientVersion>("https://clientsettingscdn.roblox.com" + path);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.Logger.WriteLine(LOG_IDENT, "Failed to contact clientsettingscdn! Falling back to clientsettings...");
|
||||
App.Logger.WriteException(LOG_IDENT, ex);
|
||||
|
||||
deployInfoResponse = await App.HttpClient.GetAsync("https://clientsettings.roblox.com" + path);
|
||||
clientVersion = await Http.GetJson<ClientVersion>("https://clientsettings.roblox.com" + path);
|
||||
}
|
||||
|
||||
string rawResponse = await deployInfoResponse.Content.ReadAsStringAsync();
|
||||
|
||||
if (!deployInfoResponse.IsSuccessStatusCode)
|
||||
// check if channel is behind LIVE
|
||||
if (!isDefaultChannel)
|
||||
{
|
||||
// 400 = Invalid binaryType.
|
||||
// 404 = Could not find version details for binaryType.
|
||||
// 500 = Error while fetching version information.
|
||||
// either way, we throw
|
||||
var defaultClientVersion = await GetInfo(DefaultChannel);
|
||||
|
||||
App.Logger.WriteLine(LOG_IDENT,
|
||||
"Failed to fetch deploy info!\r\n" +
|
||||
$"\tStatus code: {deployInfoResponse.StatusCode}\r\n" +
|
||||
$"\tResponse: {rawResponse}"
|
||||
);
|
||||
|
||||
throw new HttpResponseException(deployInfoResponse);
|
||||
if (Utilities.CompareVersions(clientVersion.Version, defaultClientVersion.Version) == VersionComparison.LessThan)
|
||||
clientVersion.IsBehindDefaultChannel = true;
|
||||
}
|
||||
|
||||
clientVersion = JsonSerializer.Deserialize<ClientVersion>(rawResponse)!;
|
||||
ClientVersionCache[cacheKey] = clientVersion;
|
||||
}
|
||||
|
||||
// check if channel is behind LIVE
|
||||
if (channel != DefaultChannel)
|
||||
{
|
||||
var defaultClientVersion = await GetInfo(DefaultChannel);
|
||||
|
||||
if (Utilities.CompareVersions(clientVersion.Version, defaultClientVersion.Version) == VersionComparison.LessThan)
|
||||
clientVersion.IsBehindDefaultChannel = true;
|
||||
}
|
||||
|
||||
ClientVersionCache[cacheKey] = clientVersion;
|
||||
|
||||
return clientVersion;
|
||||
}
|
||||
}
|
||||
|
@ -52,16 +52,7 @@ namespace Bloxstrap
|
||||
|
||||
string rawResponse = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
App.Logger.WriteLine(logIndent,
|
||||
"Failed to fetch client settings!\r\n" +
|
||||
$"\tStatus code: {response.StatusCode}\r\n" +
|
||||
$"\tResponse: {rawResponse}"
|
||||
);
|
||||
|
||||
throw new HttpResponseException(response);
|
||||
}
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var clientSettings = JsonSerializer.Deserialize<ClientFlagSettings>(rawResponse);
|
||||
|
||||
|
@ -108,7 +108,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
|
||||
public void Dialog_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (!_isClosing)
|
||||
Bootstrapper?.CancelInstall();
|
||||
Bootstrapper?.Cancel();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -105,7 +105,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
|
||||
private void Window_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (!_isClosing)
|
||||
Bootstrapper?.CancelInstall();
|
||||
Bootstrapper?.Cancel();
|
||||
}
|
||||
|
||||
#region IBootstrapperDialog Methods
|
||||
|
@ -88,7 +88,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
|
||||
private void UiWindow_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (!_isClosing)
|
||||
Bootstrapper?.CancelInstall();
|
||||
Bootstrapper?.Cancel();
|
||||
}
|
||||
|
||||
#region IBootstrapperDialog Methods
|
||||
|
@ -102,7 +102,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
|
||||
private void UiWindow_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (!_isClosing)
|
||||
Bootstrapper?.CancelInstall();
|
||||
Bootstrapper?.Cancel();
|
||||
}
|
||||
|
||||
#region IBootstrapperDialog Methods
|
||||
|
@ -49,7 +49,7 @@
|
||||
</Grid>
|
||||
</MenuItem.Header>
|
||||
</MenuItem>
|
||||
<MenuItem x:Name="ServerDetailsMenuItem" Visibility="Collapsed" Click="ServerDetailsMenuItem_Click">
|
||||
<MenuItem x:Name="ServerDetailsMenuItem" Visibility="Collapsed" Click="ServerDetailsMenuItem_Click">
|
||||
<MenuItem.Header>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@ -61,7 +61,7 @@
|
||||
</Grid>
|
||||
</MenuItem.Header>
|
||||
</MenuItem>
|
||||
<MenuItem Click="JoinLastServerMenuItem_Click">
|
||||
<MenuItem x:Name="GameHistoryMenuItem" Click="JoinLastServerMenuItem_Click" Visibility="Collapsed">
|
||||
<MenuItem.Header>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
|
@ -2,16 +2,11 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interop;
|
||||
|
||||
using Wpf.Ui.Appearance;
|
||||
using Wpf.Ui.Mvvm.Contracts;
|
||||
using Wpf.Ui.Mvvm.Services;
|
||||
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
using Bloxstrap.Integrations;
|
||||
using Bloxstrap.Resources;
|
||||
|
||||
namespace Bloxstrap.UI.Elements.ContextMenu
|
||||
{
|
||||
@ -46,6 +41,9 @@ namespace Bloxstrap.UI.Elements.ContextMenu
|
||||
if (_watcher.RichPresence is not null)
|
||||
RichPresenceMenuItem.Visibility = Visibility.Visible;
|
||||
|
||||
if (!App.Settings.Prop.UseDisableAppPatch)
|
||||
GameHistoryMenuItem.Visibility = Visibility.Visible;
|
||||
|
||||
VersionTextBlock.Text = $"{App.ProjectName} v{App.Version}";
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
Width="480"
|
||||
MinHeight="0"
|
||||
SizeToContent="Height"
|
||||
Title="{x:Static resources:Strings.Dialog_Connectivity_Title}"
|
||||
Background="{ui:ThemeResource ApplicationBackgroundBrush}"
|
||||
ExtendsContentIntoTitleBar="True"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
@ -29,9 +30,9 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Column="0" Width="32" Height="32" Margin="0,0,15,0" VerticalAlignment="Top" RenderOptions.BitmapScalingMode="HighQuality" Source="pack://application:,,,/Resources/MessageBox/Error.png" />
|
||||
<Image x:Name="IconImage" Grid.Column="0" Width="32" Height="32" Margin="0,0,15,0" VerticalAlignment="Top" RenderOptions.BitmapScalingMode="HighQuality" Source="pack://application:,,,/Resources/MessageBox/Error.png" />
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock x:Name="TitleTextBlock" Text="? is unable to connect to ?" FontSize="18" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<TextBlock x:Name="TitleTextBlock" Text="? is unable to connect to ?" FontSize="18" Foreground="{DynamicResource TextFillColorPrimaryBrush}" TextWrapping="Wrap" />
|
||||
<controls:MarkdownTextBlock x:Name="DescriptionTextBlock" MarkdownText="?" Margin="0,16,0,0" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<TextBlock Text="{x:Static resources:Strings.Dialog_Connectivity_MoreInfo}" Margin="0,16,0,0" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<RichTextBox x:Name="ErrorRichTextBox" Padding="8" Margin="0,8,0,0" Block.LineHeight="2" FontFamily="Courier New" IsReadOnly="True" />
|
||||
|
@ -1,5 +1,7 @@
|
||||
using System.Media;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
@ -14,10 +16,41 @@ namespace Bloxstrap.UI.Elements.Dialogs
|
||||
/// </summary>
|
||||
public partial class ConnectivityDialog
|
||||
{
|
||||
public ConnectivityDialog(string title, string description, Exception exception)
|
||||
public ConnectivityDialog(string title, string description, MessageBoxImage image, Exception exception)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
string? iconFilename = null;
|
||||
SystemSound? sound = null;
|
||||
|
||||
switch (image)
|
||||
{
|
||||
case MessageBoxImage.Error:
|
||||
iconFilename = "Error";
|
||||
sound = SystemSounds.Hand;
|
||||
break;
|
||||
|
||||
case MessageBoxImage.Question:
|
||||
iconFilename = "Question";
|
||||
sound = SystemSounds.Question;
|
||||
break;
|
||||
|
||||
case MessageBoxImage.Warning:
|
||||
iconFilename = "Warning";
|
||||
sound = SystemSounds.Exclamation;
|
||||
break;
|
||||
|
||||
case MessageBoxImage.Information:
|
||||
iconFilename = "Information";
|
||||
sound = SystemSounds.Asterisk;
|
||||
break;
|
||||
}
|
||||
|
||||
if (iconFilename is null)
|
||||
IconImage.Visibility = Visibility.Collapsed;
|
||||
else
|
||||
IconImage.Source = new BitmapImage(new Uri($"pack://application:,,,/Resources/MessageBox/{iconFilename}.png"));
|
||||
|
||||
TitleTextBlock.Text = title;
|
||||
DescriptionTextBlock.MarkdownText = description;
|
||||
|
||||
@ -28,7 +61,7 @@ namespace Bloxstrap.UI.Elements.Dialogs
|
||||
Close();
|
||||
};
|
||||
|
||||
SystemSounds.Hand.Play();
|
||||
sound?.Play();
|
||||
|
||||
Loaded += delegate
|
||||
{
|
||||
|
@ -33,7 +33,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Column="0" Width="32" Height="32" Margin="0,0,15,0" VerticalAlignment="Top" RenderOptions.BitmapScalingMode="HighQuality" Source="pack://application:,,,/Resources/MessageBox/Error.png" />
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock Text="{x:Static resources:Strings.Dialog_Exception_Info_1}" FontSize="18" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<TextBlock Text="{x:Static resources:Strings.Dialog_Exception_Info_1}" FontSize="18" Foreground="{DynamicResource TextFillColorPrimaryBrush}" TextWrapping="Wrap" />
|
||||
<RichTextBox x:Name="ErrorRichTextBox" Padding="8" Margin="0,16,0,0" Block.LineHeight="2" FontFamily="Courier New" IsReadOnly="True" />
|
||||
<controls:MarkdownTextBlock x:Name="HelpMessageMDTextBlock" Margin="0,16,0,0" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
</StackPanel>
|
||||
|
@ -9,6 +9,7 @@ using Bloxstrap.UI.Elements.Installer.Pages;
|
||||
using Bloxstrap.UI.Elements.Base;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using Bloxstrap.Resources;
|
||||
|
||||
namespace Bloxstrap.UI.Elements.Installer
|
||||
{
|
||||
@ -102,7 +103,7 @@ namespace Bloxstrap.UI.Elements.Installer
|
||||
if (Finished)
|
||||
return;
|
||||
|
||||
var result = Frontend.ShowMessageBox("Are you sure you want to cancel the installation?", MessageBoxImage.Warning, MessageBoxButton.YesNo);
|
||||
var result = Frontend.ShowMessageBox(Strings.Installer_ShouldCancel, MessageBoxImage.Warning, MessageBoxButton.YesNo);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
e.Cancel = true;
|
||||
|
@ -14,6 +14,8 @@ namespace Bloxstrap.UI.Elements.Settings
|
||||
/// </summary>
|
||||
public partial class MainWindow : INavigationWindow
|
||||
{
|
||||
private Models.Persistable.WindowState _state => App.State.Prop.SettingsWindow;
|
||||
|
||||
public MainWindow(bool showAlreadyRunningWarning)
|
||||
{
|
||||
var viewModel = new MainWindowViewModel();
|
||||
@ -33,6 +35,30 @@ namespace Bloxstrap.UI.Elements.Settings
|
||||
|
||||
if (showAlreadyRunningWarning)
|
||||
ShowAlreadyRunningSnackbar();
|
||||
|
||||
LoadState();
|
||||
}
|
||||
|
||||
public void LoadState()
|
||||
{
|
||||
if (_state.Left > SystemParameters.VirtualScreenWidth)
|
||||
_state.Left = 0;
|
||||
|
||||
if (_state.Top > SystemParameters.VirtualScreenHeight)
|
||||
_state.Top = 0;
|
||||
|
||||
if (_state.Width > 0)
|
||||
this.Width = _state.Width;
|
||||
|
||||
if (_state.Height > 0)
|
||||
this.Height = _state.Height;
|
||||
|
||||
if (_state.Left > 0 && _state.Top > 0)
|
||||
{
|
||||
this.WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
this.Left = _state.Left;
|
||||
this.Top = _state.Top;
|
||||
}
|
||||
}
|
||||
|
||||
private async void ShowAlreadyRunningSnackbar()
|
||||
@ -67,6 +93,14 @@ namespace Bloxstrap.UI.Elements.Settings
|
||||
e.Cancel = true;
|
||||
}
|
||||
|
||||
_state.Width = this.Width;
|
||||
_state.Height = this.Height;
|
||||
|
||||
_state.Top = this.Top;
|
||||
_state.Left = this.Left;
|
||||
|
||||
App.State.Save();
|
||||
|
||||
if (!e.Cancel)
|
||||
App.Terminate();
|
||||
}
|
||||
|
@ -165,12 +165,6 @@
|
||||
</ComboBox>
|
||||
</controls:OptionControl>
|
||||
|
||||
<controls:OptionControl
|
||||
Header="{x:Static resources:Strings.Menu_FastFlags_Presets_AltGraphicsSelector_Title}"
|
||||
Description="{x:Static resources:Strings.Menu_FastFlags_Presets_AltGraphicsSelector_Description}">
|
||||
<ui:ToggleSwitch IsChecked="{Binding AlternateGraphicsSelectorEnabled, Mode=TwoWay}" />
|
||||
</controls:OptionControl>
|
||||
|
||||
<ui:CardAction Margin="0,24,0,0" Icon="EditSettings24" Command="{Binding OpenFastFlagEditorCommand}">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14" Text="{x:Static resources:Strings.Menu_FastFlagEditor_Title}" />
|
||||
|
@ -96,7 +96,7 @@
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<TextBlock Text="{x:Static resources:Strings.Common_Name}" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
<ui:TextBox Margin="0,4,0,0" Text="{Binding SelectedCustomIntegration.Name}" />
|
||||
<ui:TextBox Margin="0,4,0,0" Text="{Binding SelectedCustomIntegration.Name, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBlock Margin="0,8,0,0" Text="{x:Static resources:Strings.Menu_Integrations_Custom_AppLocation}" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
|
||||
<Grid Margin="0,4,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
@ -25,18 +25,27 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ui:CardAction Grid.Row="0" Grid.Column="0" x:Name="OpenModFolderCardAction" Margin="0,0,4,0" Icon="Folder24" Command="{Binding OpenModsFolderCommand}">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14" Text="{x:Static resources:Strings.Menu_Mods_OpenModsFolder_Title}" TextWrapping="Wrap" />
|
||||
<TextBlock Margin="0,2,0,0" FontSize="12" Text="{x:Static resources:Strings.Menu_Mods_OpenModsFolder_Description}" Foreground="{DynamicResource TextFillColorTertiaryBrush}" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</ui:CardAction>
|
||||
|
||||
<ui:CardAction Grid.Row="0" Grid.Column="1" Margin="4,0,0,0" Icon="BookQuestionMark24" Command="models:GlobalViewModel.OpenWebpageCommand" CommandParameter="https://github.com/pizzaboxer/bloxstrap/wiki/Adding-custom-mods">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14" Text="{x:Static resources:Strings.Common_Help}" />
|
||||
<TextBlock Margin="0,2,0,0" FontSize="12" Text="{x:Static resources:Strings.Menu_Mods_Help_Description}" Padding="0,0,16,0" Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
|
||||
</StackPanel>
|
||||
</ui:CardAction>
|
||||
|
||||
<ui:CardAction Grid.Row="1" Grid.ColumnSpan="2" Margin="0,8,0,0" Icon="WindowWrench24" Command="{Binding OpenCompatSettingsCommand}">
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14" Text="{x:Static resources:Strings.Menu_Mods_Misc_CompatibilitySettings_Title}" TextWrapping="Wrap" />
|
||||
<controls:MarkdownTextBlock Margin="0,2,0,0" FontSize="12" MarkdownText="{Binding Source={x:Static resources:Strings.Menu_Mods_Misc_CompatibilitySettings_Description}, Converter={StaticResource StringFormatConverter}, ConverterParameter='https://devblogs.microsoft.com/directx/demystifying-full-screen-optimizations/'}" Foreground="{DynamicResource TextFillColorTertiaryBrush}" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</ui:CardAction>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="{x:Static resources:Strings.Common_Presets}" FontSize="20" FontWeight="Medium" Margin="0,16,0,0" />
|
||||
@ -93,13 +102,5 @@
|
||||
<ui:Button Icon="Delete16" Content="{x:Static resources:Strings.Menu_Mods_Misc_CustomFont_Remove}" Appearance="Danger" Command="{Binding ManageCustomFontCommand}" Visibility="{Binding DeleteCustomFontVisibility, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</controls:OptionControl>
|
||||
|
||||
<controls:OptionControl
|
||||
Header="{x:Static resources:Strings.Menu_Mods_Misc_DisableFullscreenOptimisations_Title}"
|
||||
Description="{x:Static resources:Strings.Menu_Mods_Misc_DisableFullscreenOptimisations_Description}"
|
||||
HelpLink="https://devblogs.microsoft.com/directx/demystifying-full-screen-optimizations/"
|
||||
x:Name="FullscreenOptimizationsToggle">
|
||||
<ui:ToggleSwitch IsChecked="{Binding DisableFullscreenOptimizations, Mode=TwoWay}" />
|
||||
</controls:OptionControl>
|
||||
</StackPanel>
|
||||
</ui:UiPage>
|
||||
|
@ -1,6 +1,4 @@
|
||||
using System.Windows;
|
||||
|
||||
using Bloxstrap.UI.ViewModels.Settings;
|
||||
using Bloxstrap.UI.ViewModels.Settings;
|
||||
|
||||
namespace Bloxstrap.UI.Elements.Settings.Pages
|
||||
{
|
||||
@ -13,10 +11,6 @@ namespace Bloxstrap.UI.Elements.Settings.Pages
|
||||
{
|
||||
DataContext = new ModsViewModel();
|
||||
InitializeComponent();
|
||||
|
||||
// fullscreen optimizations were only added in windows 10 build 17093
|
||||
if (Environment.OSVersion.Version.Build < 17093)
|
||||
this.FullscreenOptimizationsToggle.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,20 +17,7 @@ namespace Bloxstrap.UI
|
||||
if (App.LaunchSettings.QuietFlag.Active)
|
||||
return defaultResult;
|
||||
|
||||
if (App.LaunchSettings.RobloxLaunchMode != LaunchMode.None)
|
||||
return ShowFluentMessageBox(message, icon, buttons);
|
||||
|
||||
switch (App.Settings.Prop.BootstrapperStyle)
|
||||
{
|
||||
case BootstrapperStyle.FluentDialog:
|
||||
case BootstrapperStyle.ClassicFluentDialog:
|
||||
case BootstrapperStyle.FluentAeroDialog:
|
||||
case BootstrapperStyle.ByfronDialog:
|
||||
return ShowFluentMessageBox(message, icon, buttons);
|
||||
|
||||
default:
|
||||
return MessageBox.Show(message, App.ProjectName, buttons, icon);
|
||||
}
|
||||
return ShowFluentMessageBox(message, icon, buttons);
|
||||
}
|
||||
|
||||
public static void ShowPlayerErrorDialog(bool crash = false)
|
||||
@ -49,17 +36,23 @@ namespace Bloxstrap.UI
|
||||
|
||||
public static void ShowExceptionDialog(Exception exception)
|
||||
{
|
||||
if (App.LaunchSettings.QuietFlag.Active)
|
||||
return;
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
new ExceptionDialog(exception).ShowDialog();
|
||||
});
|
||||
}
|
||||
|
||||
public static void ShowConnectivityDialog(string title, string description, Exception exception)
|
||||
public static void ShowConnectivityDialog(string title, string description, MessageBoxImage image, Exception exception)
|
||||
{
|
||||
if (App.LaunchSettings.QuietFlag.Active)
|
||||
return;
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
new ConnectivityDialog(title, description, exception).ShowDialog();
|
||||
new ConnectivityDialog(title, description, image, exception).ShowDialog();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ namespace Bloxstrap.UI
|
||||
if (_activityWatcher is null)
|
||||
return;
|
||||
|
||||
string serverLocation = await _activityWatcher.Data.QueryServerLocation();
|
||||
string? serverLocation = await _activityWatcher.Data.QueryServerLocation();
|
||||
|
||||
if (string.IsNullOrEmpty(serverLocation))
|
||||
return;
|
||||
|
@ -35,7 +35,7 @@ namespace Bloxstrap.UI.ViewModels.Bootstrapper
|
||||
|
||||
private void CancelInstall()
|
||||
{
|
||||
_dialog.Bootstrapper?.CancelInstall();
|
||||
_dialog.Bootstrapper?.Cancel();
|
||||
_dialog.CloseBootstrapper();
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
||||
|
||||
public ICommand CopyInstanceIdCommand => new RelayCommand(CopyInstanceId);
|
||||
|
||||
public EventHandler? RequestCloseEvent;
|
||||
|
||||
public ServerInformationViewModel(Watcher watcher)
|
||||
{
|
||||
_activityWatcher = watcher.ActivityWatcher!;
|
||||
@ -31,7 +29,13 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu
|
||||
|
||||
public async void QueryServerLocation()
|
||||
{
|
||||
ServerLocation = await _activityWatcher.Data.QueryServerLocation();
|
||||
string? location = await _activityWatcher.Data.QueryServerLocation();
|
||||
|
||||
if (String.IsNullOrEmpty(location))
|
||||
ServerLocation = Strings.Common_NotAvailable;
|
||||
else
|
||||
ServerLocation = location;
|
||||
|
||||
OnPropertyChanged(nameof(ServerLocation));
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,6 @@
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Bloxstrap.Resources;
|
||||
|
||||
using Microsoft.Win32;
|
||||
using Wpf.Ui.Mvvm.Interfaces;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Bloxstrap.UI.ViewModels.Installer
|
||||
{
|
||||
public class InstallViewModel : NotifyPropertyChangedViewModel
|
||||
|
@ -27,20 +27,20 @@
|
||||
{
|
||||
// wouldnt it be better to check old version guids?
|
||||
// what about fresh installs?
|
||||
get => String.IsNullOrEmpty(App.State.Prop.PlayerVersionGuid) && String.IsNullOrEmpty(App.State.Prop.StudioVersionGuid);
|
||||
get => String.IsNullOrEmpty(App.State.Prop.Player.VersionGuid) && String.IsNullOrEmpty(App.State.Prop.Studio.VersionGuid);
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
_oldPlayerVersionGuid = App.State.Prop.PlayerVersionGuid;
|
||||
_oldStudioVersionGuid = App.State.Prop.StudioVersionGuid;
|
||||
App.State.Prop.PlayerVersionGuid = "";
|
||||
App.State.Prop.StudioVersionGuid = "";
|
||||
_oldPlayerVersionGuid = App.State.Prop.Player.VersionGuid;
|
||||
_oldStudioVersionGuid = App.State.Prop.Studio.VersionGuid;
|
||||
App.State.Prop.Player.VersionGuid = "";
|
||||
App.State.Prop.Studio.VersionGuid = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
App.State.Prop.PlayerVersionGuid = _oldPlayerVersionGuid;
|
||||
App.State.Prop.StudioVersionGuid = _oldStudioVersionGuid;
|
||||
App.State.Prop.Player.VersionGuid = _oldPlayerVersionGuid;
|
||||
App.State.Prop.Studio.VersionGuid = _oldStudioVersionGuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,12 +96,6 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
||||
set => App.FastFlags.SetPreset("Rendering.DisableScaling", value ? "True" : null);
|
||||
}
|
||||
|
||||
public bool AlternateGraphicsSelectorEnabled
|
||||
{
|
||||
get => App.FastFlags.GetPreset("UI.Menu.GraphicsSlider") == "True";
|
||||
set => App.FastFlags.SetPreset("UI.Menu.GraphicsSlider", value ? "True" : null);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<InGameMenuVersion, Dictionary<string, string?>> IGMenuVersions => FastFlagManager.IGMenuVersions;
|
||||
|
||||
public InGameMenuVersion SelectedIGMenuVersion
|
||||
|
@ -1,8 +1,6 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
|
||||
using Bloxstrap.Resources;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
@ -12,7 +10,9 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
||||
public class IntegrationsViewModel : NotifyPropertyChangedViewModel
|
||||
{
|
||||
public ICommand AddIntegrationCommand => new RelayCommand(AddIntegration);
|
||||
|
||||
public ICommand DeleteIntegrationCommand => new RelayCommand(DeleteIntegration);
|
||||
|
||||
public ICommand BrowseIntegrationLocationCommand => new RelayCommand(BrowseIntegrationLocation);
|
||||
|
||||
private void AddIntegration()
|
||||
@ -57,6 +57,7 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
||||
if (dialog.ShowDialog() != true)
|
||||
return;
|
||||
|
||||
SelectedCustomIntegration.Name = dialog.SafeFileName;
|
||||
SelectedCustomIntegration.Location = dialog.FileName;
|
||||
OnPropertyChanged(nameof(SelectedCustomIntegration));
|
||||
}
|
||||
|
@ -3,9 +3,14 @@ using System.Windows.Input;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.UI.Shell;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Bloxstrap.Models.SettingTasks;
|
||||
using Bloxstrap.AppData;
|
||||
|
||||
namespace Bloxstrap.UI.ViewModels.Settings
|
||||
{
|
||||
@ -59,6 +64,8 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
||||
|
||||
public ICommand ManageCustomFontCommand => new RelayCommand(ManageCustomFont);
|
||||
|
||||
public ICommand OpenCompatSettingsCommand => new RelayCommand(OpenCompatSettings);
|
||||
|
||||
public ModPresetTask OldDeathSoundTask { get; } = new("OldDeathSound", @"content\sounds\ouch.ogg", "Sounds.OldDeath.ogg");
|
||||
|
||||
public ModPresetTask OldAvatarBackgroundTask { get; } = new("OldAvatarBackground", @"ExtraContent\places\Mobile.rbxl", "OldAvatarBackground.rbxl");
|
||||
@ -96,10 +103,15 @@ namespace Bloxstrap.UI.ViewModels.Settings
|
||||
|
||||
public FontModPresetTask TextFontTask { get; } = new();
|
||||
|
||||
public bool DisableFullscreenOptimizations
|
||||
private void OpenCompatSettings()
|
||||
{
|
||||
get => App.Settings.Prop.DisableFullscreenOptimizations;
|
||||
set => App.Settings.Prop.DisableFullscreenOptimizations = value;
|
||||
string path = new RobloxPlayerData().ExecutablePath;
|
||||
|
||||
if (File.Exists(path))
|
||||
PInvoke.SHObjectProperties(HWND.Null, SHOP_TYPE.SHOP_FILEPATH, path, "Compatibility");
|
||||
else
|
||||
Frontend.ShowMessageBox(Strings.Common_RobloxNotInstalled, MessageBoxImage.Error);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System.ComponentModel;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace Bloxstrap
|
||||
{
|
||||
@ -51,10 +50,9 @@ namespace Bloxstrap
|
||||
|
||||
public static string GetRobloxVersion(bool studio)
|
||||
{
|
||||
string versionGuid = studio ? App.State.Prop.StudioVersionGuid : App.State.Prop.PlayerVersionGuid;
|
||||
string fileName = studio ? "RobloxStudioBeta.exe" : "RobloxPlayerBeta.exe";
|
||||
string fileName = studio ? "Studio/RobloxStudioBeta.exe" : "Player/RobloxPlayerBeta.exe";
|
||||
|
||||
string playerLocation = Path.Combine(Paths.Versions, versionGuid, fileName);
|
||||
string playerLocation = Path.Combine(Paths.Roblox, fileName);
|
||||
|
||||
if (!File.Exists(playerLocation))
|
||||
return "";
|
||||
|
@ -1,20 +0,0 @@
|
||||
namespace Bloxstrap.Utility
|
||||
{
|
||||
public static class AsyncHelpers
|
||||
{
|
||||
public static void ExceptionHandler(Task task, object? state)
|
||||
{
|
||||
const string LOG_IDENT = "AsyncHelpers::ExceptionHandler";
|
||||
|
||||
if (task.Exception is null)
|
||||
return;
|
||||
|
||||
if (state is null)
|
||||
App.Logger.WriteLine(LOG_IDENT, "An exception occurred while running the task");
|
||||
else
|
||||
App.Logger.WriteLine(LOG_IDENT, $"An exception occurred while running the task '{state}'");
|
||||
|
||||
App.FinalizeExceptionHandling(task.Exception);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,12 @@
|
||||
using System.Web;
|
||||
using System.Windows;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Bloxstrap
|
||||
namespace Bloxstrap.Utility
|
||||
{
|
||||
static class ProtocolHandler
|
||||
static class WindowsRegistry
|
||||
{
|
||||
private const string RobloxPlaceKey = "Roblox.Place";
|
||||
|
||||
public static void Register(string key, string name, string handler, string handlerParam = "%1")
|
||||
public static void RegisterProtocol(string key, string name, string handler, string handlerParam = "%1")
|
||||
{
|
||||
string handlerArgs = $"\"{handler}\" {handlerParam}";
|
||||
|
||||
@ -30,10 +27,56 @@ namespace Bloxstrap
|
||||
}
|
||||
}
|
||||
|
||||
public static void RegisterRobloxPlace(string handler)
|
||||
/// <summary>
|
||||
/// Registers Roblox Player protocols for Bloxstrap
|
||||
/// </summary>
|
||||
public static void RegisterPlayer() => RegisterPlayer(Paths.Application, "-player \"%1\"");
|
||||
|
||||
public static void RegisterPlayer(string handler, string handlerParam)
|
||||
{
|
||||
RegisterProtocol("roblox", "Roblox", handler, handlerParam);
|
||||
RegisterProtocol("roblox-player", "Roblox", handler, handlerParam);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all Roblox Studio classes for Bloxstrap
|
||||
/// </summary>
|
||||
public static void RegisterStudio()
|
||||
{
|
||||
RegisterStudioProtocol(Paths.Application, "-studio \"%1\"");
|
||||
RegisterStudioFileClass(Paths.Application, "-studio \"%1\"");
|
||||
RegisterStudioFileTypes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers roblox-studio and roblox-studio-auth protocols
|
||||
/// </summary>
|
||||
/// <param name="handler"></param>
|
||||
/// <param name="handlerParam"></param>
|
||||
public static void RegisterStudioProtocol(string handler, string handlerParam)
|
||||
{
|
||||
RegisterProtocol("roblox-studio", "Roblox", handler, handlerParam);
|
||||
RegisterProtocol("roblox-studio-auth", "Roblox", handler, handlerParam);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers file associations for Roblox.Place class
|
||||
/// </summary>
|
||||
public static void RegisterStudioFileTypes()
|
||||
{
|
||||
RegisterStudioFileType(".rbxl");
|
||||
RegisterStudioFileType(".rbxlx");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers Roblox.Place class
|
||||
/// </summary>
|
||||
/// <param name="handler"></param>
|
||||
/// <param name="handlerParam"></param>
|
||||
public static void RegisterStudioFileClass(string handler, string handlerParam)
|
||||
{
|
||||
const string keyValue = "Roblox Place";
|
||||
string handlerArgs = $"\"{handler}\" -ide \"%1\"";
|
||||
string handlerArgs = $"\"{handler}\" {handlerParam}";
|
||||
string iconValue = $"{handler},0";
|
||||
|
||||
using RegistryKey uriKey = Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + RobloxPlaceKey);
|
||||
@ -54,7 +97,7 @@ namespace Bloxstrap
|
||||
uriIconKey.SetValue("", iconValue);
|
||||
}
|
||||
|
||||
public static void RegisterExtension(string key)
|
||||
public static void RegisterStudioFileType(string key)
|
||||
{
|
||||
using RegistryKey uriKey = Registry.CurrentUser.CreateSubKey($@"Software\Classes\{key}");
|
||||
uriKey.CreateSubKey(RobloxPlaceKey + @"\ShellNew");
|
@ -31,7 +31,7 @@ namespace Bloxstrap
|
||||
#if DEBUG
|
||||
if (String.IsNullOrEmpty(watcherData))
|
||||
{
|
||||
string path = Path.Combine(Paths.Versions, App.State.Prop.PlayerVersionGuid, "RobloxPlayerBeta.exe");
|
||||
string path = Path.Combine(Paths.Roblox, "Player", "RobloxPlayerBeta.exe");
|
||||
using var gameClientProcess = Process.Start(path);
|
||||
_gameClientPid = gameClientProcess.Id;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user