mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Updates and bugfixes for v1.3.0
- Features - Added integration with rbxfpsunlocker - Added support for user-applicable mods - Added ability to disable auto-update checking - Misc - Removed Bloxstrap branding from Discord Rich Presence - Mod presets for old death sound and mouse cursor are now statically stored as base64 strings, eliminating reliance on the website and the old cursors still existing - Bugfixes - Fixed vista bootstrapper style not hiding properly and improper behavior when closed - Fixed forms not being brought to the front when shown - Code - Reconsolidated Bootstrapper to a single file, using regions instead of partials
This commit is contained in:
parent
85de225226
commit
92b159d682
@ -4,13 +4,14 @@
|
|||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<Platforms>AnyCPU;x86</Platforms>
|
<Platforms>AnyCPU;x86</Platforms>
|
||||||
<ApplicationIcon>Bloxstrap.ico</ApplicationIcon>
|
<ApplicationIcon>Bloxstrap.ico</ApplicationIcon>
|
||||||
<Version>1.2.0</Version>
|
<Version>1.3.0</Version>
|
||||||
<FileVersion>1.2.0.0</FileVersion>
|
<FileVersion>1.3.0.0</FileVersion>
|
||||||
|
<UseWPF>True</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -27,12 +28,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Dialogs\BootstrapperStyles\LegacyDialog2009.cs">
|
<Compile Update="Dialogs\BootstrapperStyles\LegacyDialog2009.cs" />
|
||||||
<SubType>Form</SubType>
|
<Compile Update="Dialogs\BootstrapperStyles\ProgressDialogDark.cs" />
|
||||||
</Compile>
|
|
||||||
<Compile Update="Dialogs\BootstrapperStyles\ProgressDialogDark.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Properties\Resources.Designer.cs">
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
|
795
Bloxstrap/Bootstrapper.cs
Normal file
795
Bloxstrap/Bootstrapper.cs
Normal file
@ -0,0 +1,795 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
using Bloxstrap.Enums;
|
||||||
|
using Bloxstrap.Dialogs.BootstrapperStyles;
|
||||||
|
using Bloxstrap.Helpers;
|
||||||
|
using Bloxstrap.Helpers.Integrations;
|
||||||
|
using Bloxstrap.Helpers.RSMM;
|
||||||
|
|
||||||
|
namespace Bloxstrap
|
||||||
|
{
|
||||||
|
public partial class Bootstrapper
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
private string? LaunchCommandLine;
|
||||||
|
|
||||||
|
private string VersionGuid;
|
||||||
|
private PackageManifest VersionPackageManifest;
|
||||||
|
private FileManifest VersionFileManifest;
|
||||||
|
private string VersionFolder;
|
||||||
|
|
||||||
|
private readonly bool FreshInstall;
|
||||||
|
|
||||||
|
private int ProgressIncrement;
|
||||||
|
private bool CancelFired = false;
|
||||||
|
|
||||||
|
private static readonly HttpClient Client = new();
|
||||||
|
|
||||||
|
// in case a new package is added, you can find the corresponding directory
|
||||||
|
// by opening the stock bootstrapper in a hex editor
|
||||||
|
// TODO - there ideally should be a less static way to do this that's not hardcoded?
|
||||||
|
private static readonly IReadOnlyDictionary<string, string> PackageDirectories = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "RobloxApp.zip", @"" },
|
||||||
|
{ "shaders.zip", @"shaders\" },
|
||||||
|
{ "ssl.zip", @"ssl\" },
|
||||||
|
|
||||||
|
{ "content-avatar.zip", @"content\avatar\" },
|
||||||
|
{ "content-configs.zip", @"content\configs\" },
|
||||||
|
{ "content-fonts.zip", @"content\fonts\" },
|
||||||
|
{ "content-sky.zip", @"content\sky\" },
|
||||||
|
{ "content-sounds.zip", @"content\sounds\" },
|
||||||
|
{ "content-textures2.zip", @"content\textures\" },
|
||||||
|
{ "content-models.zip", @"content\models\" },
|
||||||
|
|
||||||
|
{ "content-textures3.zip", @"PlatformContent\pc\textures\" },
|
||||||
|
{ "content-terrain.zip", @"PlatformContent\pc\terrain\" },
|
||||||
|
{ "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" },
|
||||||
|
|
||||||
|
{ "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" },
|
||||||
|
{ "extracontent-translations.zip", @"ExtraContent\translations\" },
|
||||||
|
{ "extracontent-models.zip", @"ExtraContent\models\" },
|
||||||
|
{ "extracontent-textures.zip", @"ExtraContent\textures\" },
|
||||||
|
{ "extracontent-places.zip", @"ExtraContent\places\" },
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly string AppSettings =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||||
|
"<Settings>\n" +
|
||||||
|
" <ContentFolder>content</ContentFolder>\n" +
|
||||||
|
" <BaseUrl>http://www.roblox.com</BaseUrl>\n" +
|
||||||
|
"</Settings>\n";
|
||||||
|
|
||||||
|
private static readonly string ModReadme =
|
||||||
|
"This is where you can modify your Roblox files while preserving modifications\n" +
|
||||||
|
"whenever Roblox updates.\n" +
|
||||||
|
"\n" +
|
||||||
|
"For example, Modifications\\content\\sounds\\ouch.ogg will\n" +
|
||||||
|
"overwrite Versions\\version-xxxxxxxxxxxxxxxx\\content\\sounds\\ouch.ogg\n" +
|
||||||
|
"\n" +
|
||||||
|
"If you remove a file mod from here, Bloxstrap will restore the stock version\n" +
|
||||||
|
"of the file the next time it's launched.\n" +
|
||||||
|
"\n" +
|
||||||
|
"Any files added here to the root modification directory are ignored.\n" +
|
||||||
|
"\n" +
|
||||||
|
"By default, two mod presets are provided for restoring the old death\n" +
|
||||||
|
"sound and the old mouse cursor.\n";
|
||||||
|
|
||||||
|
// TODO: reduce reliance on event handlers for signalling property changes to the bootstrapper dialog
|
||||||
|
// i mean, chances are we can just use IBootstrapperDialog now?
|
||||||
|
|
||||||
|
// public IBootstrapperDialog BootstrapperDialog;
|
||||||
|
|
||||||
|
public event EventHandler CloseDialogEvent;
|
||||||
|
public event EventHandler PromptShutdownEvent;
|
||||||
|
public event ChangeEventHandler<string> ShowSuccessEvent;
|
||||||
|
public event ChangeEventHandler<string> MessageChanged;
|
||||||
|
public event ChangeEventHandler<int> ProgressBarValueChanged;
|
||||||
|
public event ChangeEventHandler<ProgressBarStyle> ProgressBarStyleChanged;
|
||||||
|
public event ChangeEventHandler<bool> CancelEnabledChanged;
|
||||||
|
|
||||||
|
private string _message;
|
||||||
|
private int _progress = 0;
|
||||||
|
private ProgressBarStyle _progressStyle = ProgressBarStyle.Marquee;
|
||||||
|
private bool _cancelEnabled = false;
|
||||||
|
|
||||||
|
public string Message
|
||||||
|
{
|
||||||
|
get => _message;
|
||||||
|
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_message == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MessageChanged.Invoke(this, new ChangeEventArgs<string>(value));
|
||||||
|
|
||||||
|
_message = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Progress
|
||||||
|
{
|
||||||
|
get => _progress;
|
||||||
|
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_progress == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProgressBarValueChanged.Invoke(this, new ChangeEventArgs<int>(value));
|
||||||
|
|
||||||
|
_progress = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgressBarStyle ProgressStyle
|
||||||
|
{
|
||||||
|
get => _progressStyle;
|
||||||
|
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_progressStyle == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProgressBarStyleChanged.Invoke(this, new ChangeEventArgs<ProgressBarStyle>(value));
|
||||||
|
|
||||||
|
_progressStyle = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CancelEnabled
|
||||||
|
{
|
||||||
|
get => _cancelEnabled;
|
||||||
|
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_cancelEnabled == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CancelEnabledChanged.Invoke(this, new ChangeEventArgs<bool>(value));
|
||||||
|
|
||||||
|
_cancelEnabled = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Core
|
||||||
|
public Bootstrapper()
|
||||||
|
{
|
||||||
|
FreshInstall = String.IsNullOrEmpty(Program.Settings.VersionGuid);
|
||||||
|
Client.Timeout = TimeSpan.FromMinutes(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(BootstrapperStyle bootstrapperStyle, string? launchCommandLine = null)
|
||||||
|
{
|
||||||
|
LaunchCommandLine = launchCommandLine;
|
||||||
|
|
||||||
|
switch (bootstrapperStyle)
|
||||||
|
{
|
||||||
|
case BootstrapperStyle.VistaDialog:
|
||||||
|
Application.Run(new VistaDialog(this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BootstrapperStyle.LegacyDialog2009:
|
||||||
|
Application.Run(new LegacyDialog2009(this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BootstrapperStyle.LegacyDialog2011:
|
||||||
|
Application.Run(new LegacyDialog2011(this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BootstrapperStyle.ProgressDialog:
|
||||||
|
Application.Run(new ProgressDialog(this));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BootstrapperStyle.ProgressDialogDark:
|
||||||
|
Application.Run(new ProgressDialogDark(this));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Run()
|
||||||
|
{
|
||||||
|
/* Message = "hi";
|
||||||
|
Progress = 42;
|
||||||
|
ProgressStyle = ProgressBarStyle.Blocks;
|
||||||
|
CancelEnabled = true;
|
||||||
|
|
||||||
|
BootstrapperDialog.Message = "hi";
|
||||||
|
BootstrapperDialog.ProgressValue = 42;
|
||||||
|
BootstrapperDialog.ProgressStyle = ProgressBarStyle.Blocks;
|
||||||
|
BootstrapperDialog.CancelEnabled = true;
|
||||||
|
|
||||||
|
return; */
|
||||||
|
|
||||||
|
if (LaunchCommandLine == "-uninstall")
|
||||||
|
{
|
||||||
|
Uninstall();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await CheckLatestVersion();
|
||||||
|
|
||||||
|
if (!Directory.Exists(VersionFolder) || Program.Settings.VersionGuid != VersionGuid)
|
||||||
|
{
|
||||||
|
Debug.WriteLineIf(!Directory.Exists(VersionFolder), $"Installing latest version (!Directory.Exists({VersionFolder}))");
|
||||||
|
Debug.WriteLineIf(Program.Settings.VersionGuid != VersionGuid, $"Installing latest version ({Program.Settings.VersionGuid} != {VersionGuid})");
|
||||||
|
|
||||||
|
await InstallLatestVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyModifications();
|
||||||
|
|
||||||
|
if (Program.IsFirstRun)
|
||||||
|
Program.SettingsManager.ShouldSave = true;
|
||||||
|
|
||||||
|
if (Program.IsFirstRun || FreshInstall)
|
||||||
|
Register();
|
||||||
|
|
||||||
|
CheckInstall();
|
||||||
|
|
||||||
|
await RbxFpsUnlocker.CheckInstall();
|
||||||
|
|
||||||
|
await StartRoblox();
|
||||||
|
|
||||||
|
Program.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckLatestVersion()
|
||||||
|
{
|
||||||
|
Message = "Connecting to Roblox...";
|
||||||
|
|
||||||
|
VersionGuid = await Client.GetStringAsync($"{Program.BaseUrlSetup}/version");
|
||||||
|
VersionFolder = Path.Combine(Directories.Versions, VersionGuid);
|
||||||
|
VersionPackageManifest = await PackageManifest.Get(VersionGuid);
|
||||||
|
VersionFileManifest = await FileManifest.Get(VersionGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckIfRunning()
|
||||||
|
{
|
||||||
|
Process[] processes = Process.GetProcessesByName("RobloxPlayerBeta");
|
||||||
|
|
||||||
|
if (processes.Length > 0)
|
||||||
|
PromptShutdown();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// try/catch just in case process was closed before prompt was answered
|
||||||
|
|
||||||
|
foreach (Process process in processes)
|
||||||
|
{
|
||||||
|
process.CloseMainWindow();
|
||||||
|
process.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartRoblox()
|
||||||
|
{
|
||||||
|
string startEventName = Program.ProjectName.Replace(" ", "") + "StartEvent";
|
||||||
|
|
||||||
|
Message = "Starting Roblox...";
|
||||||
|
|
||||||
|
// launch time isn't really required for all launches, but it's usually just safest to do this
|
||||||
|
LaunchCommandLine += " --launchtime=" + DateTimeOffset.Now.ToUnixTimeSeconds() + " -startEvent " + startEventName;
|
||||||
|
|
||||||
|
using (SystemEvent startEvent = new(startEventName))
|
||||||
|
{
|
||||||
|
bool shouldWait = false;
|
||||||
|
|
||||||
|
Process gameClient = Process.Start(Path.Combine(VersionFolder, "RobloxPlayerBeta.exe"), LaunchCommandLine);
|
||||||
|
Process? rbxFpsUnlocker = null;
|
||||||
|
DiscordRichPresence? richPresence = null;
|
||||||
|
|
||||||
|
bool startEventFired = await startEvent.WaitForEvent();
|
||||||
|
|
||||||
|
startEvent.Close();
|
||||||
|
|
||||||
|
if (!startEventFired)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Program.Settings.RFUEnabled && Process.GetProcessesByName("rbxfpsunlocker").Length == 0)
|
||||||
|
{
|
||||||
|
ProcessStartInfo startInfo = new();
|
||||||
|
startInfo.FileName = Path.Combine(Directories.Integrations, @"rbxfpsunlocker\rbxfpsunlocker.exe");
|
||||||
|
startInfo.WorkingDirectory = Path.Combine(Directories.Integrations, "rbxfpsunlocker");
|
||||||
|
|
||||||
|
rbxFpsUnlocker = Process.Start(startInfo);
|
||||||
|
|
||||||
|
if (Program.Settings.RFUAutoclose)
|
||||||
|
shouldWait = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// event fired, wait for 6 seconds then close
|
||||||
|
await Task.Delay(6000);
|
||||||
|
|
||||||
|
// now we move onto handling rich presence
|
||||||
|
// except beta app launch since we have to rely strictly on website launch
|
||||||
|
if (Program.Settings.UseDiscordRichPresence && !LaunchCommandLine.Contains("--app"))
|
||||||
|
{
|
||||||
|
// probably not the most ideal way to do this
|
||||||
|
string? placeId = Utilities.GetKeyValue(LaunchCommandLine, "placeId=", '&');
|
||||||
|
|
||||||
|
if (placeId is not null)
|
||||||
|
{
|
||||||
|
richPresence = new DiscordRichPresence();
|
||||||
|
bool presenceSet = await richPresence.SetPresence(placeId);
|
||||||
|
|
||||||
|
if (presenceSet)
|
||||||
|
shouldWait = true;
|
||||||
|
else
|
||||||
|
richPresence.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shouldWait)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// keep bloxstrap open in the background
|
||||||
|
CloseDialog();
|
||||||
|
await gameClient.WaitForExitAsync();
|
||||||
|
|
||||||
|
if (richPresence is not null)
|
||||||
|
richPresence.Dispose();
|
||||||
|
|
||||||
|
if (Program.Settings.RFUAutoclose && rbxFpsUnlocker is not null)
|
||||||
|
rbxFpsUnlocker.Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelButtonClicked()
|
||||||
|
{
|
||||||
|
if (!CancelEnabled)
|
||||||
|
{
|
||||||
|
Program.Exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CancelFired = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Program.IsFirstRun)
|
||||||
|
Directory.Delete(Directories.Base, true);
|
||||||
|
else if (Directory.Exists(VersionFolder))
|
||||||
|
Directory.Delete(VersionFolder, true);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
Program.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowSuccess(string message)
|
||||||
|
{
|
||||||
|
ShowSuccessEvent.Invoke(this, new ChangeEventArgs<string>(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PromptShutdown()
|
||||||
|
{
|
||||||
|
PromptShutdownEvent.Invoke(this, new EventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseDialog()
|
||||||
|
{
|
||||||
|
CloseDialogEvent.Invoke(this, new EventArgs());
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region App Install
|
||||||
|
public static void Register()
|
||||||
|
{
|
||||||
|
RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{Program.ProjectName}");
|
||||||
|
|
||||||
|
// new install location selected, delete old one
|
||||||
|
string? oldInstallLocation = (string?)applicationKey.GetValue("OldInstallLocation");
|
||||||
|
if (!String.IsNullOrEmpty(oldInstallLocation) && oldInstallLocation != Directories.Base)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(oldInstallLocation))
|
||||||
|
Directory.Delete(oldInstallLocation, true);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
applicationKey.DeleteValue("OldInstallLocation");
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationKey.SetValue("InstallLocation", Directories.Base);
|
||||||
|
applicationKey.Close();
|
||||||
|
|
||||||
|
// set uninstall key
|
||||||
|
RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Program.ProjectName}");
|
||||||
|
uninstallKey.SetValue("DisplayIcon", $"{Directories.App},0");
|
||||||
|
uninstallKey.SetValue("DisplayName", Program.ProjectName);
|
||||||
|
uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd"));
|
||||||
|
uninstallKey.SetValue("InstallLocation", Directories.Base);
|
||||||
|
uninstallKey.SetValue("NoRepair", 1);
|
||||||
|
uninstallKey.SetValue("Publisher", Program.ProjectName);
|
||||||
|
uninstallKey.SetValue("ModifyPath", $"\"{Directories.App}\" -preferences");
|
||||||
|
uninstallKey.SetValue("UninstallString", $"\"{Directories.App}\" -uninstall");
|
||||||
|
uninstallKey.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CheckInstall()
|
||||||
|
{
|
||||||
|
// check if launch uri is set to our bootstrapper
|
||||||
|
// this doesn't go under register, so we check every launch
|
||||||
|
// just in case the stock bootstrapper changes it back
|
||||||
|
|
||||||
|
Protocol.Register("roblox", "Roblox", Directories.App);
|
||||||
|
Protocol.Register("roblox-player", "Roblox", Directories.App);
|
||||||
|
|
||||||
|
// in case the user is reinstalling
|
||||||
|
if (File.Exists(Directories.App) && Program.IsFirstRun)
|
||||||
|
File.Delete(Directories.App);
|
||||||
|
|
||||||
|
// check to make sure bootstrapper is in the install folder
|
||||||
|
if (!File.Exists(Directories.App) && Environment.ProcessPath is not null)
|
||||||
|
File.Copy(Environment.ProcessPath, Directories.App);
|
||||||
|
|
||||||
|
// this SHOULD go under Register(),
|
||||||
|
// but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall
|
||||||
|
// maybe in a later version?
|
||||||
|
if (!Directory.Exists(Program.StartMenu))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Program.StartMenu);
|
||||||
|
|
||||||
|
ShellLink.Shortcut.CreateShortcut(Directories.App, "", Directories.App, 0)
|
||||||
|
.WriteToFile(Path.Combine(Program.StartMenu, "Play Roblox.lnk"));
|
||||||
|
|
||||||
|
ShellLink.Shortcut.CreateShortcut(Directories.App, "-preferences", Directories.App, 0)
|
||||||
|
.WriteToFile(Path.Combine(Program.StartMenu, $"Configure {Program.ProjectName}.lnk"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Uninstall()
|
||||||
|
{
|
||||||
|
CheckIfRunning();
|
||||||
|
|
||||||
|
Message = $"Uninstalling {Program.ProjectName}...";
|
||||||
|
|
||||||
|
Program.SettingsManager.ShouldSave = false;
|
||||||
|
|
||||||
|
// check if stock bootstrapper is still installed
|
||||||
|
RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player");
|
||||||
|
if (bootstrapperKey is null)
|
||||||
|
{
|
||||||
|
Protocol.Unregister("roblox");
|
||||||
|
Protocol.Unregister("roblox-player");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// revert launch uri handler to stock bootstrapper
|
||||||
|
|
||||||
|
string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe";
|
||||||
|
|
||||||
|
Protocol.Register("roblox", "Roblox", bootstrapperLocation);
|
||||||
|
Protocol.Register("roblox-player", "Roblox", bootstrapperLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// delete application key
|
||||||
|
Registry.CurrentUser.DeleteSubKey($@"Software\{Program.ProjectName}");
|
||||||
|
|
||||||
|
// delete start menu folder
|
||||||
|
Directory.Delete(Program.StartMenu, true);
|
||||||
|
|
||||||
|
// delete uninstall key
|
||||||
|
Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Program.ProjectName}");
|
||||||
|
|
||||||
|
// delete installation folder
|
||||||
|
// (should delete everything except bloxstrap itself)
|
||||||
|
Directory.Delete(Directories.Base, true);
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
|
||||||
|
ShowSuccess($"{Program.ProjectName} has been uninstalled");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Roblox Install
|
||||||
|
private async Task InstallLatestVersion()
|
||||||
|
{
|
||||||
|
CheckIfRunning();
|
||||||
|
|
||||||
|
if (FreshInstall)
|
||||||
|
Message = "Installing Roblox...";
|
||||||
|
else
|
||||||
|
Message = "Upgrading Roblox...";
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Directories.Base);
|
||||||
|
|
||||||
|
CancelEnabled = true;
|
||||||
|
|
||||||
|
// i believe the original bootstrapper bases the progress bar off zip
|
||||||
|
// extraction progress, but here i'm doing package download progress
|
||||||
|
|
||||||
|
ProgressStyle = ProgressBarStyle.Continuous;
|
||||||
|
|
||||||
|
ProgressIncrement = (int)Math.Floor((decimal)1 / VersionPackageManifest.Count * 100);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Directories.Downloads);
|
||||||
|
|
||||||
|
foreach (Package package in VersionPackageManifest)
|
||||||
|
{
|
||||||
|
// no await, download all the packages at once
|
||||||
|
DownloadPackage(package);
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// wait for download to finish (and also round off the progress bar if needed)
|
||||||
|
|
||||||
|
if (Progress == ProgressIncrement * VersionPackageManifest.Count)
|
||||||
|
Progress = 100;
|
||||||
|
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
while (Progress != 100);
|
||||||
|
|
||||||
|
ProgressStyle = ProgressBarStyle.Marquee;
|
||||||
|
|
||||||
|
Debug.WriteLine("Finished downloading");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Directories.Versions);
|
||||||
|
|
||||||
|
foreach (Package package in VersionPackageManifest)
|
||||||
|
{
|
||||||
|
// extract all the packages at once (shouldn't be too heavy on cpu?)
|
||||||
|
ExtractPackage(package);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine("Finished extracting packages");
|
||||||
|
|
||||||
|
Message = "Configuring Roblox...";
|
||||||
|
|
||||||
|
string appSettingsLocation = Path.Combine(VersionFolder, "AppSettings.xml");
|
||||||
|
await File.WriteAllTextAsync(appSettingsLocation, AppSettings);
|
||||||
|
|
||||||
|
if (!FreshInstall)
|
||||||
|
{
|
||||||
|
// let's take this opportunity to delete any packages we don't need anymore
|
||||||
|
foreach (string filename in Directory.GetFiles(Directories.Downloads))
|
||||||
|
{
|
||||||
|
if (!VersionPackageManifest.Exists(package => filename.Contains(package.Signature)))
|
||||||
|
File.Delete(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VersionGuid != Program.Settings.VersionGuid)
|
||||||
|
{
|
||||||
|
// and also to delete our old version folder
|
||||||
|
Directory.Delete(Path.Combine(Directories.Versions, Program.Settings.VersionGuid), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CancelEnabled = false;
|
||||||
|
|
||||||
|
Program.Settings.VersionGuid = VersionGuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyModifications()
|
||||||
|
{
|
||||||
|
string modFolder = Path.Combine(Directories.Modifications);
|
||||||
|
string manifestFile = Path.Combine(Directories.Base, "ModManifest.txt");
|
||||||
|
|
||||||
|
List<string> manifestFiles = new();
|
||||||
|
List<string> modFolderFiles = new();
|
||||||
|
|
||||||
|
if (!Directory.Exists(modFolder))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(modFolder);
|
||||||
|
File.WriteAllText(Path.Combine(modFolder, "README.txt"), ModReadme);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckModPreset(Program.Settings.UseOldDeathSound, @"content\sounds\ouch.ogg", Program.Base64OldDeathSound);
|
||||||
|
CheckModPreset(Program.Settings.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowCursor.png", Program.Base64OldArrowCursor);
|
||||||
|
CheckModPreset(Program.Settings.UseOldMouseCursor, @"content\textures\Cursors\KeyboardMouse\ArrowFarCursor.png", Program.Base64OldArrowFarCursor);
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(modFolder, "*.*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
// get relative directory path
|
||||||
|
string relativeFile = file.Substring(modFolder.Length + 1);
|
||||||
|
|
||||||
|
// ignore files placed in the root directory
|
||||||
|
if (!relativeFile.Contains(@"\"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
modFolderFiles.Add(relativeFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the manifest is primarily here to keep track of what files have been
|
||||||
|
// deleted from the modifications folder, so that we know when to restore the
|
||||||
|
// original files from the downloaded packages
|
||||||
|
|
||||||
|
if (File.Exists(manifestFile))
|
||||||
|
manifestFiles = File.ReadAllLines(manifestFile).ToList<string>();
|
||||||
|
else
|
||||||
|
manifestFiles = modFolderFiles;
|
||||||
|
|
||||||
|
// copy and overwrite
|
||||||
|
foreach (string file in modFolderFiles)
|
||||||
|
{
|
||||||
|
string fileModFolder = Path.Combine(modFolder, file);
|
||||||
|
string fileVersionFolder = Path.Combine(VersionFolder, file);
|
||||||
|
|
||||||
|
if (File.Exists(fileVersionFolder))
|
||||||
|
{
|
||||||
|
if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
File.Copy(fileModFolder, fileVersionFolder, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we check for files that have been deleted from the mod folder
|
||||||
|
foreach (string fileLocation in manifestFiles)
|
||||||
|
{
|
||||||
|
if (modFolderFiles.Contains(fileLocation))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
KeyValuePair<string, string> packageDirectory;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
packageDirectory = PackageDirectories.First(x => x.Key != "RobloxApp.zip" && fileLocation.StartsWith(x.Value));
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// package doesn't exist, likely mistakenly placed file
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore original file
|
||||||
|
string fileName = fileLocation.Substring(packageDirectory.Value.Length);
|
||||||
|
ExtractFileFromPackage(packageDirectory.Key, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllLines(manifestFile, modFolderFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckModPreset(bool condition, string location, string base64Contents)
|
||||||
|
{
|
||||||
|
string modFolderLocation = Path.Combine(Directories.Modifications, location);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(modFolderLocation));
|
||||||
|
|
||||||
|
if (condition)
|
||||||
|
{
|
||||||
|
if (!File.Exists(modFolderLocation))
|
||||||
|
{
|
||||||
|
File.WriteAllBytes(modFolderLocation, Convert.FromBase64String(base64Contents));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (File.Exists(modFolderLocation))
|
||||||
|
{
|
||||||
|
File.Delete(modFolderLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void DownloadPackage(Package package)
|
||||||
|
{
|
||||||
|
string packageUrl = $"{Program.BaseUrlSetup}/{VersionGuid}-{package.Name}";
|
||||||
|
string packageLocation = Path.Combine(Directories.Downloads, package.Signature);
|
||||||
|
string robloxPackageLocation = Path.Combine(Program.LocalAppData, "Roblox", "Downloads", package.Signature);
|
||||||
|
|
||||||
|
if (File.Exists(packageLocation))
|
||||||
|
{
|
||||||
|
FileInfo file = new(packageLocation);
|
||||||
|
|
||||||
|
string calculatedMD5 = Utilities.MD5File(packageLocation);
|
||||||
|
if (calculatedMD5 != package.Signature)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"{package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading...");
|
||||||
|
file.Delete();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"{package.Name} is already downloaded, skipping...");
|
||||||
|
Progress += ProgressIncrement;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (File.Exists(robloxPackageLocation))
|
||||||
|
{
|
||||||
|
// let's cheat! if the stock bootstrapper already previously downloaded the file,
|
||||||
|
// then we can just copy the one from there
|
||||||
|
|
||||||
|
Debug.WriteLine($"Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder...");
|
||||||
|
File.Copy(robloxPackageLocation, packageLocation);
|
||||||
|
Progress += ProgressIncrement;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(packageLocation))
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Downloading {package.Name}...");
|
||||||
|
|
||||||
|
var response = await Client.GetAsync(packageUrl);
|
||||||
|
|
||||||
|
if (CancelFired)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (var fileStream = new FileStream(packageLocation, FileMode.CreateNew))
|
||||||
|
{
|
||||||
|
await response.Content.CopyToAsync(fileStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine($"Finished downloading {package.Name}!");
|
||||||
|
Progress += ProgressIncrement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtractPackage(Package package)
|
||||||
|
{
|
||||||
|
if (CancelFired)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string packageLocation = Path.Combine(Directories.Downloads, package.Signature);
|
||||||
|
string packageFolder = Path.Combine(VersionFolder, PackageDirectories[package.Name]);
|
||||||
|
string extractPath;
|
||||||
|
|
||||||
|
Debug.WriteLine($"Extracting {package.Name} to {packageFolder}...");
|
||||||
|
|
||||||
|
using (ZipArchive archive = ZipFile.OpenRead(packageLocation))
|
||||||
|
{
|
||||||
|
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||||
|
{
|
||||||
|
if (CancelFired)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (entry.FullName.EndsWith(@"\"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
extractPath = Path.Combine(packageFolder, entry.FullName);
|
||||||
|
|
||||||
|
Debug.WriteLine($"[{package.Name}] Writing {extractPath}...");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(extractPath));
|
||||||
|
|
||||||
|
if (File.Exists(extractPath))
|
||||||
|
File.Delete(extractPath);
|
||||||
|
|
||||||
|
entry.ExtractToFile(extractPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtractFileFromPackage(string packageName, string fileName)
|
||||||
|
{
|
||||||
|
Package? package = VersionPackageManifest.Find(x => x.Name == packageName);
|
||||||
|
|
||||||
|
if (package is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DownloadPackage(package);
|
||||||
|
|
||||||
|
string packageLocation = Path.Combine(Directories.Downloads, package.Signature);
|
||||||
|
string packageFolder = Path.Combine(VersionFolder, PackageDirectories[package.Name]);
|
||||||
|
|
||||||
|
using (ZipArchive archive = ZipFile.OpenRead(packageLocation))
|
||||||
|
{
|
||||||
|
ZipArchiveEntry? entry = archive.Entries.Where(x => x.FullName == fileName).FirstOrDefault();
|
||||||
|
|
||||||
|
if (entry is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string fileLocation = Path.Combine(packageFolder, entry.FullName);
|
||||||
|
|
||||||
|
if (File.Exists(fileLocation))
|
||||||
|
File.Delete(fileLocation);
|
||||||
|
|
||||||
|
entry.ExtractToFile(fileLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -1,125 +0,0 @@
|
|||||||
using Microsoft.Win32;
|
|
||||||
using Bloxstrap.Helpers;
|
|
||||||
|
|
||||||
namespace Bloxstrap
|
|
||||||
{
|
|
||||||
partial class Bootstrapper
|
|
||||||
{
|
|
||||||
public static void Register()
|
|
||||||
{
|
|
||||||
if (Program.BaseDirectory is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{Program.ProjectName}");
|
|
||||||
|
|
||||||
// new install location selected, delete old one
|
|
||||||
string? oldInstallLocation = (string?)applicationKey.GetValue("OldInstallLocation");
|
|
||||||
if (!String.IsNullOrEmpty(oldInstallLocation) && oldInstallLocation != Program.BaseDirectory)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Directory.Exists(oldInstallLocation))
|
|
||||||
Directory.Delete(oldInstallLocation, true);
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
applicationKey.DeleteValue("OldInstallLocation");
|
|
||||||
}
|
|
||||||
|
|
||||||
applicationKey.SetValue("InstallLocation", Program.BaseDirectory);
|
|
||||||
applicationKey.Close();
|
|
||||||
|
|
||||||
// set uninstall key
|
|
||||||
RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Program.ProjectName}");
|
|
||||||
uninstallKey.SetValue("DisplayIcon", $"{Program.FilePath},0");
|
|
||||||
uninstallKey.SetValue("DisplayName", Program.ProjectName);
|
|
||||||
uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd"));
|
|
||||||
uninstallKey.SetValue("InstallLocation", Program.BaseDirectory);
|
|
||||||
uninstallKey.SetValue("NoRepair", 1);
|
|
||||||
uninstallKey.SetValue("Publisher", Program.ProjectName);
|
|
||||||
uninstallKey.SetValue("ModifyPath", $"\"{Program.FilePath}\" -preferences");
|
|
||||||
uninstallKey.SetValue("UninstallString", $"\"{Program.FilePath}\" -uninstall");
|
|
||||||
uninstallKey.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CheckInstall()
|
|
||||||
{
|
|
||||||
// check if launch uri is set to our bootstrapper
|
|
||||||
// this doesn't go under register, so we check every launch
|
|
||||||
// just in case the stock bootstrapper changes it back
|
|
||||||
|
|
||||||
Protocol.Register("roblox", "Roblox", Program.FilePath);
|
|
||||||
Protocol.Register("roblox-player", "Roblox", Program.FilePath);
|
|
||||||
|
|
||||||
// in case the user is reinstalling
|
|
||||||
if (File.Exists(Program.FilePath) && Program.IsFirstRun)
|
|
||||||
File.Delete(Program.FilePath);
|
|
||||||
|
|
||||||
// check to make sure bootstrapper is in the install folder
|
|
||||||
if (!File.Exists(Program.FilePath) && Environment.ProcessPath is not null)
|
|
||||||
File.Copy(Environment.ProcessPath, Program.FilePath);
|
|
||||||
|
|
||||||
// this SHOULD go under Register(),
|
|
||||||
// but then people who have Bloxstrap v1.0.0 installed won't have this without a reinstall
|
|
||||||
// maybe in a later version?
|
|
||||||
if (!Directory.Exists(Program.StartMenuDirectory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(Program.StartMenuDirectory);
|
|
||||||
|
|
||||||
ShellLink.Shortcut.CreateShortcut(Program.FilePath, "", Program.FilePath, 0)
|
|
||||||
.WriteToFile(Path.Combine(Program.StartMenuDirectory, "Play Roblox.lnk"));
|
|
||||||
|
|
||||||
ShellLink.Shortcut.CreateShortcut(Program.FilePath, "-preferences", Program.FilePath, 0)
|
|
||||||
.WriteToFile(Path.Combine(Program.StartMenuDirectory, "Configure Bloxstrap.lnk"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Uninstall()
|
|
||||||
{
|
|
||||||
if (Program.BaseDirectory is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CheckIfRunning();
|
|
||||||
|
|
||||||
Message = $"Uninstalling {Program.ProjectName}...";
|
|
||||||
|
|
||||||
Program.SettingsManager.ShouldSave = false;
|
|
||||||
|
|
||||||
// check if stock bootstrapper is still installed
|
|
||||||
RegistryKey? bootstrapperKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\roblox-player");
|
|
||||||
if (bootstrapperKey is null)
|
|
||||||
{
|
|
||||||
Protocol.Unregister("roblox");
|
|
||||||
Protocol.Unregister("roblox-player");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// revert launch uri handler to stock bootstrapper
|
|
||||||
|
|
||||||
string bootstrapperLocation = (string?)bootstrapperKey.GetValue("InstallLocation") + "RobloxPlayerLauncher.exe";
|
|
||||||
|
|
||||||
Protocol.Register("roblox", "Roblox", bootstrapperLocation);
|
|
||||||
Protocol.Register("roblox-player", "Roblox", bootstrapperLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// delete application key
|
|
||||||
Registry.CurrentUser.DeleteSubKey($@"Software\{Program.ProjectName}");
|
|
||||||
|
|
||||||
// delete start menu folder
|
|
||||||
Directory.Delete(Program.StartMenuDirectory, true);
|
|
||||||
|
|
||||||
// delete uninstall key
|
|
||||||
Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Program.ProjectName}");
|
|
||||||
|
|
||||||
// delete installation folder
|
|
||||||
// (should delete everything except bloxstrap itself)
|
|
||||||
Directory.Delete(Program.BaseDirectory, true);
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
ShowSuccess($"{Program.ProjectName} has been uninstalled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
using Bloxstrap.Helpers.RSMM;
|
|
||||||
|
|
||||||
namespace Bloxstrap
|
|
||||||
{
|
|
||||||
partial class Bootstrapper
|
|
||||||
{
|
|
||||||
private string? LaunchCommandLine;
|
|
||||||
|
|
||||||
private string VersionGuid;
|
|
||||||
private PackageManifest VersionPackageManifest;
|
|
||||||
private FileManifest VersionFileManifest;
|
|
||||||
private string VersionFolder;
|
|
||||||
|
|
||||||
private readonly string DownloadsFolder;
|
|
||||||
private readonly bool FreshInstall;
|
|
||||||
|
|
||||||
private int ProgressIncrement;
|
|
||||||
private bool CancelFired = false;
|
|
||||||
|
|
||||||
private static readonly HttpClient Client = new();
|
|
||||||
|
|
||||||
// in case a new package is added, you can find the corresponding directory
|
|
||||||
// by opening the stock bootstrapper in a hex editor
|
|
||||||
// TODO - there ideally should be a less static way to do this that's not hardcoded?
|
|
||||||
private static readonly IReadOnlyDictionary<string, string> PackageDirectories = new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{ "RobloxApp.zip", @"" },
|
|
||||||
{ "shaders.zip", @"shaders\" },
|
|
||||||
{ "ssl.zip", @"ssl\" },
|
|
||||||
|
|
||||||
{ "content-avatar.zip", @"content\avatar\" },
|
|
||||||
{ "content-configs.zip", @"content\configs\" },
|
|
||||||
{ "content-fonts.zip", @"content\fonts\" },
|
|
||||||
{ "content-sky.zip", @"content\sky\" },
|
|
||||||
{ "content-sounds.zip", @"content\sounds\" },
|
|
||||||
{ "content-textures2.zip", @"content\textures\" },
|
|
||||||
{ "content-models.zip", @"content\models\" },
|
|
||||||
|
|
||||||
{ "content-textures3.zip", @"PlatformContent\pc\textures\" },
|
|
||||||
{ "content-terrain.zip", @"PlatformContent\pc\terrain\" },
|
|
||||||
{ "content-platform-fonts.zip", @"PlatformContent\pc\fonts\" },
|
|
||||||
|
|
||||||
{ "extracontent-luapackages.zip", @"ExtraContent\LuaPackages\" },
|
|
||||||
{ "extracontent-translations.zip", @"ExtraContent\translations\" },
|
|
||||||
{ "extracontent-models.zip", @"ExtraContent\models\" },
|
|
||||||
{ "extracontent-textures.zip", @"ExtraContent\textures\" },
|
|
||||||
{ "extracontent-places.zip", @"ExtraContent\places\" },
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string AppSettings =
|
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
|
||||||
"<Settings>\n" +
|
|
||||||
" <ContentFolder>content</ContentFolder>\n" +
|
|
||||||
" <BaseUrl>http://www.roblox.com</BaseUrl>\n" +
|
|
||||||
"</Settings>\n";
|
|
||||||
|
|
||||||
public event EventHandler CloseDialogEvent;
|
|
||||||
public event EventHandler PromptShutdownEvent;
|
|
||||||
public event ChangeEventHandler<string> ShowSuccessEvent;
|
|
||||||
public event ChangeEventHandler<string> MessageChanged;
|
|
||||||
public event ChangeEventHandler<int> ProgressBarValueChanged;
|
|
||||||
public event ChangeEventHandler<ProgressBarStyle> ProgressBarStyleChanged;
|
|
||||||
public event ChangeEventHandler<bool> CancelEnabledChanged;
|
|
||||||
|
|
||||||
private string _message;
|
|
||||||
private int _progress = 0;
|
|
||||||
private ProgressBarStyle _progressStyle = ProgressBarStyle.Marquee;
|
|
||||||
private bool _cancelEnabled = false;
|
|
||||||
|
|
||||||
public string Message
|
|
||||||
{
|
|
||||||
get => _message;
|
|
||||||
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (_message == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MessageChanged.Invoke(this, new ChangeEventArgs<string>(value));
|
|
||||||
|
|
||||||
_message = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Progress
|
|
||||||
{
|
|
||||||
get => _progress;
|
|
||||||
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (_progress == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ProgressBarValueChanged.Invoke(this, new ChangeEventArgs<int>(value));
|
|
||||||
|
|
||||||
_progress = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProgressBarStyle ProgressStyle
|
|
||||||
{
|
|
||||||
get => _progressStyle;
|
|
||||||
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (_progressStyle == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ProgressBarStyleChanged.Invoke(this, new ChangeEventArgs<ProgressBarStyle>(value));
|
|
||||||
|
|
||||||
_progressStyle = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CancelEnabled
|
|
||||||
{
|
|
||||||
get => _cancelEnabled;
|
|
||||||
|
|
||||||
private set
|
|
||||||
{
|
|
||||||
if (_cancelEnabled == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CancelEnabledChanged.Invoke(this, new ChangeEventArgs<bool>(value));
|
|
||||||
|
|
||||||
_cancelEnabled = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,243 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.IO.Compression;
|
|
||||||
|
|
||||||
using Bloxstrap.Helpers;
|
|
||||||
using Bloxstrap.Helpers.RSMM;
|
|
||||||
|
|
||||||
namespace Bloxstrap
|
|
||||||
{
|
|
||||||
partial class Bootstrapper
|
|
||||||
{
|
|
||||||
private async Task CheckLatestVersion()
|
|
||||||
{
|
|
||||||
if (Program.BaseDirectory is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Message = "Connecting to Roblox...";
|
|
||||||
|
|
||||||
VersionGuid = await Client.GetStringAsync($"{Program.BaseUrlSetup}/version");
|
|
||||||
VersionFolder = Path.Combine(Program.BaseDirectory, "Versions", VersionGuid);
|
|
||||||
VersionPackageManifest = await PackageManifest.Get(VersionGuid);
|
|
||||||
VersionFileManifest = await FileManifest.Get(VersionGuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InstallLatestVersion()
|
|
||||||
{
|
|
||||||
if (Program.BaseDirectory is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CheckIfRunning();
|
|
||||||
|
|
||||||
if (FreshInstall)
|
|
||||||
Message = "Installing Roblox...";
|
|
||||||
else
|
|
||||||
Message = "Upgrading Roblox...";
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Program.BaseDirectory);
|
|
||||||
|
|
||||||
CancelEnabled = true;
|
|
||||||
|
|
||||||
// i believe the original bootstrapper bases the progress bar off zip
|
|
||||||
// extraction progress, but here i'm doing package download progress
|
|
||||||
|
|
||||||
ProgressStyle = ProgressBarStyle.Continuous;
|
|
||||||
|
|
||||||
ProgressIncrement = (int)Math.Floor((decimal)1 / VersionPackageManifest.Count * 100);
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.Combine(Program.BaseDirectory, "Downloads"));
|
|
||||||
|
|
||||||
foreach (Package package in VersionPackageManifest)
|
|
||||||
{
|
|
||||||
// no await, download all the packages at once
|
|
||||||
DownloadPackage(package);
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// wait for download to finish (and also round off the progress bar if needed)
|
|
||||||
|
|
||||||
if (Progress == ProgressIncrement * VersionPackageManifest.Count)
|
|
||||||
Progress = 100;
|
|
||||||
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
while (Progress != 100);
|
|
||||||
|
|
||||||
ProgressStyle = ProgressBarStyle.Marquee;
|
|
||||||
|
|
||||||
Debug.WriteLine("Finished downloading");
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.Combine(Program.BaseDirectory, "Versions"));
|
|
||||||
|
|
||||||
foreach (Package package in VersionPackageManifest)
|
|
||||||
{
|
|
||||||
// extract all the packages at once (shouldn't be too heavy on cpu?)
|
|
||||||
ExtractPackage(package);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.WriteLine("Finished extracting packages");
|
|
||||||
|
|
||||||
Message = "Configuring Roblox...";
|
|
||||||
|
|
||||||
string appSettingsLocation = Path.Combine(VersionFolder, "AppSettings.xml");
|
|
||||||
await File.WriteAllTextAsync(appSettingsLocation, AppSettings);
|
|
||||||
|
|
||||||
if (!FreshInstall)
|
|
||||||
{
|
|
||||||
// let's take this opportunity to delete any packages we don't need anymore
|
|
||||||
foreach (string filename in Directory.GetFiles(DownloadsFolder))
|
|
||||||
{
|
|
||||||
if (!VersionPackageManifest.Exists(package => filename.Contains(package.Signature)))
|
|
||||||
File.Delete(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VersionGuid != Program.Settings.VersionGuid)
|
|
||||||
{
|
|
||||||
// and also to delete our old version folder
|
|
||||||
Directory.Delete(Path.Combine(Program.BaseDirectory, "Versions", Program.Settings.VersionGuid), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CancelEnabled = false;
|
|
||||||
|
|
||||||
Program.Settings.VersionGuid = VersionGuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ApplyModifications()
|
|
||||||
{
|
|
||||||
// i guess we can just assume that if the hash does not match the manifest, then it's a mod
|
|
||||||
// probably not the best way to do this? don't think file corruption is that much of a worry here
|
|
||||||
|
|
||||||
// TODO - i'm thinking i could have a manifest on my website like rbxManifest.txt
|
|
||||||
// for integrity checking and to quickly fix/alter stuff (like ouch.ogg being renamed)
|
|
||||||
// but that probably wouldn't be great to check on every run in case my webserver ever goes down
|
|
||||||
// interesting idea nonetheless, might add it sometime
|
|
||||||
|
|
||||||
// TODO - i'm hoping i can take this idea of content mods much further
|
|
||||||
// for stuff like easily installing (community-created?) texture/shader/audio mods
|
|
||||||
// but for now, let's just keep it at this
|
|
||||||
|
|
||||||
await ModifyDeathSound();
|
|
||||||
await ModifyMouseCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void DownloadPackage(Package package)
|
|
||||||
{
|
|
||||||
string packageUrl = $"{Program.BaseUrlSetup}/{VersionGuid}-{package.Name}";
|
|
||||||
string packageLocation = Path.Combine(DownloadsFolder, package.Signature);
|
|
||||||
string robloxPackageLocation = Path.Combine(Program.LocalAppData, "Roblox", "Downloads", package.Signature);
|
|
||||||
|
|
||||||
if (File.Exists(packageLocation))
|
|
||||||
{
|
|
||||||
FileInfo file = new(packageLocation);
|
|
||||||
|
|
||||||
string calculatedMD5 = Utilities.CalculateMD5(packageLocation);
|
|
||||||
if (calculatedMD5 != package.Signature)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"{package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading...");
|
|
||||||
file.Delete();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"{package.Name} is already downloaded, skipping...");
|
|
||||||
Progress += ProgressIncrement;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (File.Exists(robloxPackageLocation))
|
|
||||||
{
|
|
||||||
// let's cheat! if the stock bootstrapper already previously downloaded the file,
|
|
||||||
// then we can just copy the one from there
|
|
||||||
|
|
||||||
Debug.WriteLine($"Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder...");
|
|
||||||
File.Copy(robloxPackageLocation, packageLocation);
|
|
||||||
Progress += ProgressIncrement;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(packageLocation))
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"Downloading {package.Name}...");
|
|
||||||
|
|
||||||
var response = await Client.GetAsync(packageUrl);
|
|
||||||
|
|
||||||
if (CancelFired)
|
|
||||||
return;
|
|
||||||
|
|
||||||
using (var fileStream = new FileStream(packageLocation, FileMode.CreateNew))
|
|
||||||
{
|
|
||||||
await response.Content.CopyToAsync(fileStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.WriteLine($"Finished downloading {package.Name}!");
|
|
||||||
Progress += ProgressIncrement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExtractPackage(Package package)
|
|
||||||
{
|
|
||||||
if (CancelFired)
|
|
||||||
return;
|
|
||||||
|
|
||||||
string packageLocation = Path.Combine(DownloadsFolder, package.Signature);
|
|
||||||
string packageFolder = Path.Combine(VersionFolder, PackageDirectories[package.Name]);
|
|
||||||
string extractPath;
|
|
||||||
|
|
||||||
Debug.WriteLine($"Extracting {package.Name} to {packageFolder}...");
|
|
||||||
|
|
||||||
using (ZipArchive archive = ZipFile.OpenRead(packageLocation))
|
|
||||||
{
|
|
||||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
|
||||||
{
|
|
||||||
if (CancelFired)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (entry.FullName.EndsWith(@"\"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
extractPath = Path.Combine(packageFolder, entry.FullName);
|
|
||||||
|
|
||||||
Debug.WriteLine($"[{package.Name}] Writing {extractPath}...");
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(extractPath));
|
|
||||||
|
|
||||||
if (File.Exists(extractPath))
|
|
||||||
File.Delete(extractPath);
|
|
||||||
|
|
||||||
entry.ExtractToFile(extractPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExtractFilesFromPackage(string packageName, string[] files)
|
|
||||||
{
|
|
||||||
Package? package = VersionPackageManifest.Find(x => x.Name == packageName);
|
|
||||||
|
|
||||||
if (package is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DownloadPackage(package);
|
|
||||||
|
|
||||||
string packageLocation = Path.Combine(DownloadsFolder, package.Signature);
|
|
||||||
string packageFolder = Path.Combine(VersionFolder, PackageDirectories[package.Name]);
|
|
||||||
|
|
||||||
using (ZipArchive archive = ZipFile.OpenRead(packageLocation))
|
|
||||||
{
|
|
||||||
foreach (string fileName in files)
|
|
||||||
{
|
|
||||||
ZipArchiveEntry? entry = archive.Entries.Where(x => x.FullName == fileName).FirstOrDefault();
|
|
||||||
|
|
||||||
if (entry is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
string fileLocation = Path.Combine(packageFolder, entry.FullName);
|
|
||||||
|
|
||||||
if (File.Exists(fileLocation))
|
|
||||||
File.Delete(fileLocation);
|
|
||||||
|
|
||||||
entry.ExtractToFile(fileLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
using Bloxstrap.Helpers;
|
|
||||||
|
|
||||||
namespace Bloxstrap
|
|
||||||
{
|
|
||||||
partial class Bootstrapper
|
|
||||||
{
|
|
||||||
private async Task ModifyDeathSound()
|
|
||||||
{
|
|
||||||
string fileContentName = "ouch.ogg";
|
|
||||||
string fileContentLocation = "content\\sounds\\ouch.ogg";
|
|
||||||
string fileLocation = Path.Combine(VersionFolder, fileContentLocation);
|
|
||||||
|
|
||||||
string officialHash = VersionFileManifest[fileContentLocation];
|
|
||||||
string currentHash = Utilities.CalculateMD5(fileLocation);
|
|
||||||
|
|
||||||
if (Program.Settings.UseOldDeathSound && currentHash == officialHash)
|
|
||||||
{
|
|
||||||
// let's get the old one!
|
|
||||||
|
|
||||||
var response = await Client.GetAsync($"{Program.BaseUrlApplication}/mods/{fileContentLocation}");
|
|
||||||
|
|
||||||
if (File.Exists(fileLocation))
|
|
||||||
File.Delete(fileLocation);
|
|
||||||
|
|
||||||
using (var fileStream = new FileStream(fileLocation, FileMode.CreateNew))
|
|
||||||
{
|
|
||||||
await response.Content.CopyToAsync(fileStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!Program.Settings.UseOldDeathSound && currentHash != officialHash)
|
|
||||||
{
|
|
||||||
// who's lame enough to ever do this?
|
|
||||||
// well, we need to re-extract the one that's in the content-sounds.zip package
|
|
||||||
|
|
||||||
string[] files = { fileContentName };
|
|
||||||
ExtractFilesFromPackage("content-sounds.zip", files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ModifyMouseCursor()
|
|
||||||
{
|
|
||||||
string baseFolder = Path.Combine(VersionFolder, "content\\textures\\");
|
|
||||||
|
|
||||||
string arrowCursor = "Cursors\\KeyboardMouse\\ArrowCursor.png";
|
|
||||||
string arrowFarCursor = "Cursors\\KeyboardMouse\\ArrowFarCursor.png";
|
|
||||||
|
|
||||||
string officialHash = VersionFileManifest["content\\textures\\Cursors\\KeyboardMouse\\ArrowCursor.png"];
|
|
||||||
string currentHash = Utilities.CalculateMD5(Path.Combine(baseFolder, arrowCursor));
|
|
||||||
|
|
||||||
if (Program.Settings.UseOldMouseCursor && currentHash == officialHash)
|
|
||||||
{
|
|
||||||
// the old cursors are actually still in the content\textures\ folder, so we can just get them from there
|
|
||||||
|
|
||||||
File.Copy(Path.Combine(baseFolder, "ArrowCursor.png"), Path.Combine(baseFolder, arrowCursor), true);
|
|
||||||
File.Copy(Path.Combine(baseFolder, "ArrowFarCursor.png"), Path.Combine(baseFolder, arrowFarCursor), true);
|
|
||||||
}
|
|
||||||
else if (!Program.Settings.UseOldMouseCursor && currentHash != officialHash)
|
|
||||||
{
|
|
||||||
string[] files = { arrowCursor, arrowFarCursor };
|
|
||||||
ExtractFilesFromPackage("content-textures2.zip", files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,187 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
using Bloxstrap.Enums;
|
|
||||||
using Bloxstrap.Dialogs.BootstrapperStyles;
|
|
||||||
using Bloxstrap.Helpers;
|
|
||||||
using Bloxstrap.Helpers.RSMM;
|
|
||||||
|
|
||||||
namespace Bloxstrap
|
|
||||||
{
|
|
||||||
public partial class Bootstrapper
|
|
||||||
{
|
|
||||||
public Bootstrapper()
|
|
||||||
{
|
|
||||||
if (Program.BaseDirectory is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FreshInstall = String.IsNullOrEmpty(Program.Settings.VersionGuid);
|
|
||||||
DownloadsFolder = Path.Combine(Program.BaseDirectory, "Downloads");
|
|
||||||
Client.Timeout = TimeSpan.FromMinutes(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize(BootstrapperStyle bootstrapperStyle, string? launchCommandLine = null)
|
|
||||||
{
|
|
||||||
LaunchCommandLine = launchCommandLine;
|
|
||||||
|
|
||||||
switch (bootstrapperStyle)
|
|
||||||
{
|
|
||||||
case BootstrapperStyle.VistaDialog:
|
|
||||||
Application.Run(new VistaDialog(this));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BootstrapperStyle.LegacyDialog2009:
|
|
||||||
Application.Run(new LegacyDialog2009(this));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BootstrapperStyle.LegacyDialog2011:
|
|
||||||
Application.Run(new LegacyDialog2011(this));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BootstrapperStyle.ProgressDialog:
|
|
||||||
Application.Run(new ProgressDialog(this));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BootstrapperStyle.ProgressDialogDark:
|
|
||||||
Application.Run(new ProgressDialogDark(this));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Run()
|
|
||||||
{
|
|
||||||
if (LaunchCommandLine == "-uninstall")
|
|
||||||
{
|
|
||||||
Uninstall();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await CheckLatestVersion();
|
|
||||||
|
|
||||||
if (!Directory.Exists(VersionFolder) || Program.Settings.VersionGuid != VersionGuid)
|
|
||||||
{
|
|
||||||
Debug.WriteLineIf(!Directory.Exists(VersionFolder), $"Installing latest version (!Directory.Exists({VersionFolder}))");
|
|
||||||
Debug.WriteLineIf(Program.Settings.VersionGuid != VersionGuid, $"Installing latest version ({Program.Settings.VersionGuid} != {VersionGuid})");
|
|
||||||
|
|
||||||
await InstallLatestVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
// yes, doing this for every start is stupid, but the death sound mod is dynamically toggleable after all
|
|
||||||
ApplyModifications();
|
|
||||||
|
|
||||||
if (Program.IsFirstRun)
|
|
||||||
Program.SettingsManager.ShouldSave = true;
|
|
||||||
|
|
||||||
if (Program.IsFirstRun || FreshInstall)
|
|
||||||
Register();
|
|
||||||
|
|
||||||
CheckInstall();
|
|
||||||
|
|
||||||
await StartRoblox();
|
|
||||||
|
|
||||||
Program.Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckIfRunning()
|
|
||||||
{
|
|
||||||
Process[] processes = Process.GetProcessesByName("RobloxPlayerBeta");
|
|
||||||
|
|
||||||
if (processes.Length > 0)
|
|
||||||
PromptShutdown();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// try/catch just in case process was closed before prompt was answered
|
|
||||||
|
|
||||||
foreach (Process process in processes)
|
|
||||||
{
|
|
||||||
process.CloseMainWindow();
|
|
||||||
process.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task StartRoblox()
|
|
||||||
{
|
|
||||||
string startEventName = Program.ProjectName.Replace(" ", "") + "StartEvent";
|
|
||||||
|
|
||||||
Message = "Starting Roblox...";
|
|
||||||
|
|
||||||
// launch time isn't really required for all launches, but it's usually just safest to do this
|
|
||||||
LaunchCommandLine += " --launchtime=" + DateTimeOffset.Now.ToUnixTimeSeconds() + " -startEvent " + startEventName;
|
|
||||||
|
|
||||||
using (SystemEvent startEvent = new(startEventName))
|
|
||||||
{
|
|
||||||
Process gameClient = Process.Start(Path.Combine(VersionFolder, "RobloxPlayerBeta.exe"), LaunchCommandLine);
|
|
||||||
|
|
||||||
bool startEventFired = await startEvent.WaitForEvent();
|
|
||||||
|
|
||||||
startEvent.Close();
|
|
||||||
|
|
||||||
if (!startEventFired)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// event fired, wait for 6 seconds then close
|
|
||||||
await Task.Delay(6000);
|
|
||||||
|
|
||||||
// now we move onto handling rich presence
|
|
||||||
// except beta app launch since we have to rely strictly on website launch
|
|
||||||
if (!Program.Settings.UseDiscordRichPresence || LaunchCommandLine.Contains("--app"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// probably not the most ideal way to do this
|
|
||||||
string? placeId = Utilities.GetKeyValue(LaunchCommandLine, "placeId=", '&');
|
|
||||||
|
|
||||||
if (placeId is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// keep bloxstrap open to handle rich presence
|
|
||||||
using (DiscordRichPresence richPresence = new())
|
|
||||||
{
|
|
||||||
bool presenceSet = await richPresence.SetPresence(placeId);
|
|
||||||
|
|
||||||
if (!presenceSet)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CloseDialog();
|
|
||||||
|
|
||||||
await gameClient.WaitForExitAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CancelButtonClicked()
|
|
||||||
{
|
|
||||||
if (Program.BaseDirectory is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CancelFired = true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Program.IsFirstRun)
|
|
||||||
Directory.Delete(Program.BaseDirectory, true);
|
|
||||||
else if (Directory.Exists(VersionFolder))
|
|
||||||
Directory.Delete(VersionFolder, true);
|
|
||||||
}
|
|
||||||
catch (Exception) { }
|
|
||||||
|
|
||||||
Program.Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowSuccess(string message)
|
|
||||||
{
|
|
||||||
ShowSuccessEvent.Invoke(this, new ChangeEventArgs<string>(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PromptShutdown()
|
|
||||||
{
|
|
||||||
PromptShutdownEvent.Invoke(this, new EventArgs());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CloseDialog()
|
|
||||||
{
|
|
||||||
CloseDialogEvent.Invoke(this, new EventArgs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,9 @@
|
|||||||
using System.Diagnostics;
|
using Bloxstrap.Helpers;
|
||||||
|
|
||||||
using Bloxstrap.Helpers;
|
|
||||||
using Bloxstrap.Helpers.RSMM;
|
using Bloxstrap.Helpers.RSMM;
|
||||||
|
|
||||||
namespace Bloxstrap.Dialogs.BootstrapperStyles
|
namespace Bloxstrap.Dialogs.BootstrapperStyles
|
||||||
{
|
{
|
||||||
public class BootstrapperStyleForm : Form, IBootstrapperStyle
|
public class BootstrapperStyleForm : Form, IBootstrapperDialog
|
||||||
{
|
{
|
||||||
public Bootstrapper? Bootstrapper { get; set; }
|
public Bootstrapper? Bootstrapper { get; set; }
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Bloxstrap.Dialogs.BootstrapperStyles
|
namespace Bloxstrap.Dialogs.BootstrapperStyles
|
||||||
{
|
{
|
||||||
interface IBootstrapperStyle
|
public interface IBootstrapperDialog
|
||||||
{
|
{
|
||||||
Bootstrapper? Bootstrapper { get; set; }
|
Bootstrapper? Bootstrapper { get; set; }
|
||||||
|
|
@ -80,6 +80,7 @@
|
|||||||
this.Name = "LegacyDialog2009";
|
this.Name = "LegacyDialog2009";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "LegacyDialog2009";
|
this.Text = "LegacyDialog2009";
|
||||||
|
this.Load += new System.EventHandler(this.LegacyDialog2009_Load);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,5 +37,10 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
|
|||||||
|
|
||||||
SetupDialog();
|
SetupDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LegacyDialog2009_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
this.buttonCancel.Visible = false;
|
this.buttonCancel.Visible = false;
|
||||||
this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click);
|
this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click);
|
||||||
//
|
//
|
||||||
// LegacyDialog
|
// LegacyDialog2011
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
@ -93,6 +93,7 @@
|
|||||||
this.Name = "LegacyDialog2011";
|
this.Name = "LegacyDialog2011";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "LegacyDialog2011";
|
this.Text = "LegacyDialog2011";
|
||||||
|
this.Load += new System.EventHandler(this.LegacyDialog2011_Load);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
@ -41,5 +41,10 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
|
|||||||
|
|
||||||
SetupDialog();
|
SetupDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LegacyDialog2011_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,7 @@
|
|||||||
this.Name = "ProgressDialog";
|
this.Name = "ProgressDialog";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "ProgressDialog";
|
this.Text = "ProgressDialog";
|
||||||
|
this.Load += new System.EventHandler(this.ProgressDialog_Load);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.buttonCancel)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.buttonCancel)).EndInit();
|
||||||
this.panel1.ResumeLayout(false);
|
this.panel1.ResumeLayout(false);
|
||||||
|
@ -50,5 +50,10 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
|
|||||||
{
|
{
|
||||||
this.buttonCancel.Image = Properties.Resources.CancelButton;
|
this.buttonCancel.Image = Properties.Resources.CancelButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ProgressDialog_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@
|
|||||||
this.Name = "ProgressDialogDark";
|
this.Name = "ProgressDialogDark";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "ProgressDialog";
|
this.Text = "ProgressDialog";
|
||||||
|
this.Load += new System.EventHandler(this.ProgressDialogDark_Load);
|
||||||
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.IconBox)).EndInit();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.buttonCancel)).EndInit();
|
((System.ComponentModel.ISupportInitialize)(this.buttonCancel)).EndInit();
|
||||||
this.panel1.ResumeLayout(false);
|
this.panel1.ResumeLayout(false);
|
||||||
|
@ -50,5 +50,10 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
|
|||||||
{
|
{
|
||||||
this.buttonCancel.Image = Properties.Resources.DarkCancelButton;
|
this.buttonCancel.Image = Properties.Resources.DarkCancelButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ProgressDialogDark_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,15 +30,17 @@
|
|||||||
{
|
{
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// TestDialog
|
// VistaDialog
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(0, 0);
|
this.ClientSize = new System.Drawing.Size(0, 0);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||||
this.Name = "VistaDialog";
|
this.Name = "VistaDialog";
|
||||||
|
this.Opacity = 0D;
|
||||||
this.ShowInTaskbar = false;
|
this.ShowInTaskbar = false;
|
||||||
this.Text = "VistaDialog";
|
this.Text = "VistaDialog";
|
||||||
|
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
|
||||||
this.Load += new System.EventHandler(this.TestDialog_Load);
|
this.Load += new System.EventHandler(this.TestDialog_Load);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
@ -163,7 +163,6 @@ namespace Bloxstrap.Dialogs.BootstrapperStyles
|
|||||||
|
|
||||||
private void TestDialog_Load(object sender, EventArgs e)
|
private void TestDialog_Load(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
this.Hide();
|
|
||||||
TaskDialog.ShowDialog(Dialog);
|
TaskDialog.ShowDialog(Dialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
140
Bloxstrap/Dialogs/Preferences.Designer.cs
generated
140
Bloxstrap/Dialogs/Preferences.Designer.cs
generated
@ -32,6 +32,10 @@
|
|||||||
this.label1 = new System.Windows.Forms.Label();
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
this.Tabs = new System.Windows.Forms.TabControl();
|
this.Tabs = new System.Windows.Forms.TabControl();
|
||||||
this.DialogTab = new System.Windows.Forms.TabPage();
|
this.DialogTab = new System.Windows.Forms.TabPage();
|
||||||
|
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||||
|
this.RFUWebsite = new System.Windows.Forms.LinkLabel();
|
||||||
|
this.ToggleRFUAutoclose = new System.Windows.Forms.CheckBox();
|
||||||
|
this.ToggleRFUEnabled = new System.Windows.Forms.CheckBox();
|
||||||
this.groupBox5 = new System.Windows.Forms.GroupBox();
|
this.groupBox5 = new System.Windows.Forms.GroupBox();
|
||||||
this.ToggleRPCButtons = new System.Windows.Forms.CheckBox();
|
this.ToggleRPCButtons = new System.Windows.Forms.CheckBox();
|
||||||
this.ToggleDiscordRichPresence = new System.Windows.Forms.CheckBox();
|
this.ToggleDiscordRichPresence = new System.Windows.Forms.CheckBox();
|
||||||
@ -42,6 +46,8 @@
|
|||||||
this.StyleSelection = new System.Windows.Forms.ListBox();
|
this.StyleSelection = new System.Windows.Forms.ListBox();
|
||||||
this.InstallationTab = new System.Windows.Forms.TabPage();
|
this.InstallationTab = new System.Windows.Forms.TabPage();
|
||||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
||||||
|
this.LabelModFolderInstall = new System.Windows.Forms.Label();
|
||||||
|
this.ButtonOpenModFolder = new System.Windows.Forms.Button();
|
||||||
this.ToggleMouseCursor = new System.Windows.Forms.CheckBox();
|
this.ToggleMouseCursor = new System.Windows.Forms.CheckBox();
|
||||||
this.ToggleDeathSound = new System.Windows.Forms.CheckBox();
|
this.ToggleDeathSound = new System.Windows.Forms.CheckBox();
|
||||||
this.GroupBoxInstallLocation = new System.Windows.Forms.GroupBox();
|
this.GroupBoxInstallLocation = new System.Windows.Forms.GroupBox();
|
||||||
@ -49,11 +55,13 @@
|
|||||||
this.InstallLocation = new System.Windows.Forms.TextBox();
|
this.InstallLocation = new System.Windows.Forms.TextBox();
|
||||||
this.SaveButton = new System.Windows.Forms.Button();
|
this.SaveButton = new System.Windows.Forms.Button();
|
||||||
this.panel1 = new System.Windows.Forms.Panel();
|
this.panel1 = new System.Windows.Forms.Panel();
|
||||||
|
this.ToggleCheckForUpdates = new System.Windows.Forms.CheckBox();
|
||||||
this.PreviewButton = new System.Windows.Forms.Button();
|
this.PreviewButton = new System.Windows.Forms.Button();
|
||||||
this.InstallLocationBrowseDialog = new System.Windows.Forms.FolderBrowserDialog();
|
this.InstallLocationBrowseDialog = new System.Windows.Forms.FolderBrowserDialog();
|
||||||
this.InfoTooltip = new System.Windows.Forms.ToolTip(this.components);
|
this.InfoTooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||||
this.Tabs.SuspendLayout();
|
this.Tabs.SuspendLayout();
|
||||||
this.DialogTab.SuspendLayout();
|
this.DialogTab.SuspendLayout();
|
||||||
|
this.groupBox1.SuspendLayout();
|
||||||
this.groupBox5.SuspendLayout();
|
this.groupBox5.SuspendLayout();
|
||||||
this.groupBox3.SuspendLayout();
|
this.groupBox3.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.IconPreview)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.IconPreview)).BeginInit();
|
||||||
@ -86,6 +94,7 @@
|
|||||||
//
|
//
|
||||||
// DialogTab
|
// DialogTab
|
||||||
//
|
//
|
||||||
|
this.DialogTab.Controls.Add(this.groupBox1);
|
||||||
this.DialogTab.Controls.Add(this.groupBox5);
|
this.DialogTab.Controls.Add(this.groupBox5);
|
||||||
this.DialogTab.Controls.Add(this.groupBox3);
|
this.DialogTab.Controls.Add(this.groupBox3);
|
||||||
this.DialogTab.Controls.Add(this.groupBox2);
|
this.DialogTab.Controls.Add(this.groupBox2);
|
||||||
@ -97,13 +106,70 @@
|
|||||||
this.DialogTab.Text = "Bootstrapper";
|
this.DialogTab.Text = "Bootstrapper";
|
||||||
this.DialogTab.UseVisualStyleBackColor = true;
|
this.DialogTab.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
|
// groupBox1
|
||||||
|
//
|
||||||
|
this.groupBox1.Controls.Add(this.RFUWebsite);
|
||||||
|
this.groupBox1.Controls.Add(this.ToggleRFUAutoclose);
|
||||||
|
this.groupBox1.Controls.Add(this.ToggleRFUEnabled);
|
||||||
|
this.groupBox1.Location = new System.Drawing.Point(192, 146);
|
||||||
|
this.groupBox1.Name = "groupBox1";
|
||||||
|
this.groupBox1.Size = new System.Drawing.Size(235, 67);
|
||||||
|
this.groupBox1.TabIndex = 8;
|
||||||
|
this.groupBox1.TabStop = false;
|
||||||
|
this.groupBox1.Text = "FPS Unlocker";
|
||||||
|
//
|
||||||
|
// RFUWebsite
|
||||||
|
//
|
||||||
|
this.RFUWebsite.BackColor = System.Drawing.Color.White;
|
||||||
|
this.RFUWebsite.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||||
|
this.RFUWebsite.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
|
||||||
|
this.RFUWebsite.Location = new System.Drawing.Point(174, 0);
|
||||||
|
this.RFUWebsite.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.RFUWebsite.Name = "RFUWebsite";
|
||||||
|
this.RFUWebsite.Size = new System.Drawing.Size(55, 18);
|
||||||
|
this.RFUWebsite.TabIndex = 2;
|
||||||
|
this.RFUWebsite.TabStop = true;
|
||||||
|
this.RFUWebsite.Tag = "";
|
||||||
|
this.RFUWebsite.Text = "(website)";
|
||||||
|
this.RFUWebsite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.RFUWebsite_LinkClicked);
|
||||||
|
//
|
||||||
|
// ToggleRFUAutoclose
|
||||||
|
//
|
||||||
|
this.ToggleRFUAutoclose.AutoSize = true;
|
||||||
|
this.ToggleRFUAutoclose.Checked = true;
|
||||||
|
this.ToggleRFUAutoclose.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||||
|
this.ToggleRFUAutoclose.Location = new System.Drawing.Point(9, 40);
|
||||||
|
this.ToggleRFUAutoclose.Name = "ToggleRFUAutoclose";
|
||||||
|
this.ToggleRFUAutoclose.Size = new System.Drawing.Size(209, 19);
|
||||||
|
this.ToggleRFUAutoclose.TabIndex = 1;
|
||||||
|
this.ToggleRFUAutoclose.Text = "Automatically close on Roblox exit";
|
||||||
|
this.InfoTooltip.SetToolTip(this.ToggleRFUAutoclose, "If enabled, rbxfpsunlocker will automatically close when Roblox is closed.");
|
||||||
|
this.ToggleRFUAutoclose.UseVisualStyleBackColor = true;
|
||||||
|
this.ToggleRFUAutoclose.CheckedChanged += new System.EventHandler(this.ToggleRFUAutoclose_CheckedChanged);
|
||||||
|
//
|
||||||
|
// ToggleRFUEnabled
|
||||||
|
//
|
||||||
|
this.ToggleRFUEnabled.AutoSize = true;
|
||||||
|
this.ToggleRFUEnabled.Checked = true;
|
||||||
|
this.ToggleRFUEnabled.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||||
|
this.ToggleRFUEnabled.Location = new System.Drawing.Point(9, 19);
|
||||||
|
this.ToggleRFUEnabled.Name = "ToggleRFUEnabled";
|
||||||
|
this.ToggleRFUEnabled.Size = new System.Drawing.Size(127, 19);
|
||||||
|
this.ToggleRFUEnabled.TabIndex = 0;
|
||||||
|
this.ToggleRFUEnabled.Text = "Use rbxfpsunlocker";
|
||||||
|
this.InfoTooltip.SetToolTip(this.ToggleRFUEnabled, "If enabled, rbxfpsunlocker is downloaded.\r\nWhen Roblox is started, rbxfpsunlocker" +
|
||||||
|
" will automatically start too, \r\nbeing minimized to your system tray by default." +
|
||||||
|
"");
|
||||||
|
this.ToggleRFUEnabled.UseVisualStyleBackColor = true;
|
||||||
|
this.ToggleRFUEnabled.CheckedChanged += new System.EventHandler(this.ToggleRFUEnabled_CheckedChanged);
|
||||||
|
//
|
||||||
// groupBox5
|
// groupBox5
|
||||||
//
|
//
|
||||||
this.groupBox5.Controls.Add(this.ToggleRPCButtons);
|
this.groupBox5.Controls.Add(this.ToggleRPCButtons);
|
||||||
this.groupBox5.Controls.Add(this.ToggleDiscordRichPresence);
|
this.groupBox5.Controls.Add(this.ToggleDiscordRichPresence);
|
||||||
this.groupBox5.Location = new System.Drawing.Point(5, 146);
|
this.groupBox5.Location = new System.Drawing.Point(5, 146);
|
||||||
this.groupBox5.Name = "groupBox5";
|
this.groupBox5.Name = "groupBox5";
|
||||||
this.groupBox5.Size = new System.Drawing.Size(422, 67);
|
this.groupBox5.Size = new System.Drawing.Size(179, 67);
|
||||||
this.groupBox5.TabIndex = 7;
|
this.groupBox5.TabIndex = 7;
|
||||||
this.groupBox5.TabStop = false;
|
this.groupBox5.TabStop = false;
|
||||||
this.groupBox5.Text = "Discord Rich Presence";
|
this.groupBox5.Text = "Discord Rich Presence";
|
||||||
@ -113,9 +179,11 @@
|
|||||||
this.ToggleRPCButtons.AutoSize = true;
|
this.ToggleRPCButtons.AutoSize = true;
|
||||||
this.ToggleRPCButtons.Location = new System.Drawing.Point(9, 40);
|
this.ToggleRPCButtons.Location = new System.Drawing.Point(9, 40);
|
||||||
this.ToggleRPCButtons.Name = "ToggleRPCButtons";
|
this.ToggleRPCButtons.Name = "ToggleRPCButtons";
|
||||||
this.ToggleRPCButtons.Size = new System.Drawing.Size(196, 19);
|
this.ToggleRPCButtons.Size = new System.Drawing.Size(155, 19);
|
||||||
this.ToggleRPCButtons.TabIndex = 1;
|
this.ToggleRPCButtons.TabIndex = 1;
|
||||||
this.ToggleRPCButtons.Text = "Hide activity interaction buttons";
|
this.ToggleRPCButtons.Text = "Hide interaction buttons";
|
||||||
|
this.InfoTooltip.SetToolTip(this.ToggleRPCButtons, "Choose whether the buttons to play/view game details should be hidden from your a" +
|
||||||
|
"ctivity status.");
|
||||||
this.ToggleRPCButtons.UseVisualStyleBackColor = true;
|
this.ToggleRPCButtons.UseVisualStyleBackColor = true;
|
||||||
this.ToggleRPCButtons.CheckedChanged += new System.EventHandler(this.ToggleRPCButtons_CheckedChanged);
|
this.ToggleRPCButtons.CheckedChanged += new System.EventHandler(this.ToggleRPCButtons_CheckedChanged);
|
||||||
//
|
//
|
||||||
@ -129,6 +197,9 @@
|
|||||||
this.ToggleDiscordRichPresence.Size = new System.Drawing.Size(129, 19);
|
this.ToggleDiscordRichPresence.Size = new System.Drawing.Size(129, 19);
|
||||||
this.ToggleDiscordRichPresence.TabIndex = 0;
|
this.ToggleDiscordRichPresence.TabIndex = 0;
|
||||||
this.ToggleDiscordRichPresence.Text = "Show game activity";
|
this.ToggleDiscordRichPresence.Text = "Show game activity";
|
||||||
|
this.InfoTooltip.SetToolTip(this.ToggleDiscordRichPresence, "Choose whether to show what game you\'re playing on your Discord activity status.\r" +
|
||||||
|
"\nThis will only work when you launch a game from the website, and is not support" +
|
||||||
|
"ed in the Beta App.");
|
||||||
this.ToggleDiscordRichPresence.UseVisualStyleBackColor = true;
|
this.ToggleDiscordRichPresence.UseVisualStyleBackColor = true;
|
||||||
this.ToggleDiscordRichPresence.CheckedChanged += new System.EventHandler(this.ToggleDiscordRichPresence_CheckedChanged);
|
this.ToggleDiscordRichPresence.CheckedChanged += new System.EventHandler(this.ToggleDiscordRichPresence_CheckedChanged);
|
||||||
//
|
//
|
||||||
@ -161,6 +232,7 @@
|
|||||||
this.IconSelection.Name = "IconSelection";
|
this.IconSelection.Name = "IconSelection";
|
||||||
this.IconSelection.Size = new System.Drawing.Size(100, 109);
|
this.IconSelection.Size = new System.Drawing.Size(100, 109);
|
||||||
this.IconSelection.TabIndex = 4;
|
this.IconSelection.TabIndex = 4;
|
||||||
|
this.InfoTooltip.SetToolTip(this.IconSelection, "Choose what icon the bootstrapper should use.");
|
||||||
this.IconSelection.SelectedIndexChanged += new System.EventHandler(this.IconSelection_SelectedIndexChanged);
|
this.IconSelection.SelectedIndexChanged += new System.EventHandler(this.IconSelection_SelectedIndexChanged);
|
||||||
//
|
//
|
||||||
// groupBox2
|
// groupBox2
|
||||||
@ -181,6 +253,8 @@
|
|||||||
this.StyleSelection.Name = "StyleSelection";
|
this.StyleSelection.Name = "StyleSelection";
|
||||||
this.StyleSelection.Size = new System.Drawing.Size(161, 109);
|
this.StyleSelection.Size = new System.Drawing.Size(161, 109);
|
||||||
this.StyleSelection.TabIndex = 3;
|
this.StyleSelection.TabIndex = 3;
|
||||||
|
this.InfoTooltip.SetToolTip(this.StyleSelection, "Choose how the bootstrapper dialog should look.\r\nYou can use the \'Preview\' button" +
|
||||||
|
" to preview the bootstrapper look.");
|
||||||
this.StyleSelection.SelectedIndexChanged += new System.EventHandler(this.StyleSelection_SelectedIndexChanged);
|
this.StyleSelection.SelectedIndexChanged += new System.EventHandler(this.StyleSelection_SelectedIndexChanged);
|
||||||
//
|
//
|
||||||
// InstallationTab
|
// InstallationTab
|
||||||
@ -197,15 +271,40 @@
|
|||||||
//
|
//
|
||||||
// groupBox4
|
// groupBox4
|
||||||
//
|
//
|
||||||
|
this.groupBox4.Controls.Add(this.LabelModFolderInstall);
|
||||||
|
this.groupBox4.Controls.Add(this.ButtonOpenModFolder);
|
||||||
this.groupBox4.Controls.Add(this.ToggleMouseCursor);
|
this.groupBox4.Controls.Add(this.ToggleMouseCursor);
|
||||||
this.groupBox4.Controls.Add(this.ToggleDeathSound);
|
this.groupBox4.Controls.Add(this.ToggleDeathSound);
|
||||||
this.groupBox4.Location = new System.Drawing.Point(5, 60);
|
this.groupBox4.Location = new System.Drawing.Point(5, 60);
|
||||||
this.groupBox4.Name = "groupBox4";
|
this.groupBox4.Name = "groupBox4";
|
||||||
this.groupBox4.Size = new System.Drawing.Size(422, 65);
|
this.groupBox4.Size = new System.Drawing.Size(422, 95);
|
||||||
this.groupBox4.TabIndex = 2;
|
this.groupBox4.TabIndex = 2;
|
||||||
this.groupBox4.TabStop = false;
|
this.groupBox4.TabStop = false;
|
||||||
this.groupBox4.Text = "Modifications";
|
this.groupBox4.Text = "Modifications";
|
||||||
//
|
//
|
||||||
|
// LabelModFolderInstall
|
||||||
|
//
|
||||||
|
this.LabelModFolderInstall.AutoSize = true;
|
||||||
|
this.LabelModFolderInstall.Location = new System.Drawing.Point(6, 67);
|
||||||
|
this.LabelModFolderInstall.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
this.LabelModFolderInstall.Name = "LabelModFolderInstall";
|
||||||
|
this.LabelModFolderInstall.Size = new System.Drawing.Size(329, 15);
|
||||||
|
this.LabelModFolderInstall.TabIndex = 7;
|
||||||
|
this.LabelModFolderInstall.Text = "Other modifications can be added once Bloxstrap is installed.";
|
||||||
|
this.LabelModFolderInstall.Visible = false;
|
||||||
|
//
|
||||||
|
// ButtonOpenModFolder
|
||||||
|
//
|
||||||
|
this.ButtonOpenModFolder.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
||||||
|
this.ButtonOpenModFolder.Location = new System.Drawing.Point(8, 62);
|
||||||
|
this.ButtonOpenModFolder.Name = "ButtonOpenModFolder";
|
||||||
|
this.ButtonOpenModFolder.Size = new System.Drawing.Size(122, 25);
|
||||||
|
this.ButtonOpenModFolder.TabIndex = 6;
|
||||||
|
this.ButtonOpenModFolder.Text = "Open Mod Folder";
|
||||||
|
this.InfoTooltip.SetToolTip(this.ButtonOpenModFolder, "Open the folder for applying Roblox client modifications.");
|
||||||
|
this.ButtonOpenModFolder.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonOpenModFolder.Click += new System.EventHandler(this.ButtonOpenModFolder_Click);
|
||||||
|
//
|
||||||
// ToggleMouseCursor
|
// ToggleMouseCursor
|
||||||
//
|
//
|
||||||
this.ToggleMouseCursor.AutoSize = true;
|
this.ToggleMouseCursor.AutoSize = true;
|
||||||
@ -246,9 +345,9 @@
|
|||||||
// InstallLocationBrowseButton
|
// InstallLocationBrowseButton
|
||||||
//
|
//
|
||||||
this.InstallLocationBrowseButton.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
this.InstallLocationBrowseButton.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
||||||
this.InstallLocationBrowseButton.Location = new System.Drawing.Point(328, 20);
|
this.InstallLocationBrowseButton.Location = new System.Drawing.Point(335, 20);
|
||||||
this.InstallLocationBrowseButton.Name = "InstallLocationBrowseButton";
|
this.InstallLocationBrowseButton.Name = "InstallLocationBrowseButton";
|
||||||
this.InstallLocationBrowseButton.Size = new System.Drawing.Size(86, 25);
|
this.InstallLocationBrowseButton.Size = new System.Drawing.Size(79, 25);
|
||||||
this.InstallLocationBrowseButton.TabIndex = 5;
|
this.InstallLocationBrowseButton.TabIndex = 5;
|
||||||
this.InstallLocationBrowseButton.Text = "Browse...";
|
this.InstallLocationBrowseButton.Text = "Browse...";
|
||||||
this.InstallLocationBrowseButton.UseVisualStyleBackColor = true;
|
this.InstallLocationBrowseButton.UseVisualStyleBackColor = true;
|
||||||
@ -260,8 +359,10 @@
|
|||||||
this.InstallLocation.Location = new System.Drawing.Point(9, 21);
|
this.InstallLocation.Location = new System.Drawing.Point(9, 21);
|
||||||
this.InstallLocation.MaxLength = 255;
|
this.InstallLocation.MaxLength = 255;
|
||||||
this.InstallLocation.Name = "InstallLocation";
|
this.InstallLocation.Name = "InstallLocation";
|
||||||
this.InstallLocation.Size = new System.Drawing.Size(312, 23);
|
this.InstallLocation.Size = new System.Drawing.Size(319, 23);
|
||||||
this.InstallLocation.TabIndex = 4;
|
this.InstallLocation.TabIndex = 4;
|
||||||
|
this.InfoTooltip.SetToolTip(this.InstallLocation, "Choose where Bloxstrap should install to.\r\nThis is useful if you typically instal" +
|
||||||
|
"l all your games to a separate storage drive.");
|
||||||
//
|
//
|
||||||
// SaveButton
|
// SaveButton
|
||||||
//
|
//
|
||||||
@ -279,6 +380,7 @@
|
|||||||
this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.panel1.BackColor = System.Drawing.SystemColors.Control;
|
this.panel1.BackColor = System.Drawing.SystemColors.Control;
|
||||||
|
this.panel1.Controls.Add(this.ToggleCheckForUpdates);
|
||||||
this.panel1.Controls.Add(this.PreviewButton);
|
this.panel1.Controls.Add(this.PreviewButton);
|
||||||
this.panel1.Controls.Add(this.SaveButton);
|
this.panel1.Controls.Add(this.SaveButton);
|
||||||
this.panel1.Location = new System.Drawing.Point(-1, 298);
|
this.panel1.Location = new System.Drawing.Point(-1, 298);
|
||||||
@ -286,6 +388,19 @@
|
|||||||
this.panel1.Size = new System.Drawing.Size(466, 42);
|
this.panel1.Size = new System.Drawing.Size(466, 42);
|
||||||
this.panel1.TabIndex = 6;
|
this.panel1.TabIndex = 6;
|
||||||
//
|
//
|
||||||
|
// ToggleCheckForUpdates
|
||||||
|
//
|
||||||
|
this.ToggleCheckForUpdates.AutoSize = true;
|
||||||
|
this.ToggleCheckForUpdates.Checked = true;
|
||||||
|
this.ToggleCheckForUpdates.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||||
|
this.ToggleCheckForUpdates.Location = new System.Drawing.Point(14, 12);
|
||||||
|
this.ToggleCheckForUpdates.Name = "ToggleCheckForUpdates";
|
||||||
|
this.ToggleCheckForUpdates.Size = new System.Drawing.Size(179, 19);
|
||||||
|
this.ToggleCheckForUpdates.TabIndex = 7;
|
||||||
|
this.ToggleCheckForUpdates.Text = "Check for updates on startup";
|
||||||
|
this.ToggleCheckForUpdates.UseVisualStyleBackColor = true;
|
||||||
|
this.ToggleCheckForUpdates.CheckedChanged += new System.EventHandler(this.ToggleCheckForUpdates_CheckedChanged);
|
||||||
|
//
|
||||||
// PreviewButton
|
// PreviewButton
|
||||||
//
|
//
|
||||||
this.PreviewButton.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
this.PreviewButton.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
|
||||||
@ -318,8 +433,11 @@
|
|||||||
this.Name = "Preferences";
|
this.Name = "Preferences";
|
||||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
this.Text = "Preferences";
|
this.Text = "Preferences";
|
||||||
|
this.Load += new System.EventHandler(this.Preferences_Load);
|
||||||
this.Tabs.ResumeLayout(false);
|
this.Tabs.ResumeLayout(false);
|
||||||
this.DialogTab.ResumeLayout(false);
|
this.DialogTab.ResumeLayout(false);
|
||||||
|
this.groupBox1.ResumeLayout(false);
|
||||||
|
this.groupBox1.PerformLayout();
|
||||||
this.groupBox5.ResumeLayout(false);
|
this.groupBox5.ResumeLayout(false);
|
||||||
this.groupBox5.PerformLayout();
|
this.groupBox5.PerformLayout();
|
||||||
this.groupBox3.ResumeLayout(false);
|
this.groupBox3.ResumeLayout(false);
|
||||||
@ -331,6 +449,7 @@
|
|||||||
this.GroupBoxInstallLocation.ResumeLayout(false);
|
this.GroupBoxInstallLocation.ResumeLayout(false);
|
||||||
this.GroupBoxInstallLocation.PerformLayout();
|
this.GroupBoxInstallLocation.PerformLayout();
|
||||||
this.panel1.ResumeLayout(false);
|
this.panel1.ResumeLayout(false);
|
||||||
|
this.panel1.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -360,5 +479,12 @@
|
|||||||
private ToolTip InfoTooltip;
|
private ToolTip InfoTooltip;
|
||||||
private CheckBox ToggleMouseCursor;
|
private CheckBox ToggleMouseCursor;
|
||||||
private CheckBox ToggleRPCButtons;
|
private CheckBox ToggleRPCButtons;
|
||||||
|
private GroupBox groupBox1;
|
||||||
|
private LinkLabel RFUWebsite;
|
||||||
|
private CheckBox ToggleRFUAutoclose;
|
||||||
|
private CheckBox ToggleRFUEnabled;
|
||||||
|
private CheckBox ToggleCheckForUpdates;
|
||||||
|
private Button ButtonOpenModFolder;
|
||||||
|
private Label LabelModFolderInstall;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,12 @@
|
|||||||
using Microsoft.Win32;
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
using Bloxstrap.Helpers;
|
|
||||||
using Bloxstrap.Enums;
|
|
||||||
using Bloxstrap.Dialogs.BootstrapperStyles;
|
using Bloxstrap.Dialogs.BootstrapperStyles;
|
||||||
|
using Bloxstrap.Enums;
|
||||||
|
using Bloxstrap.Helpers;
|
||||||
|
using Bloxstrap.Helpers.Integrations;
|
||||||
|
|
||||||
namespace Bloxstrap.Dialogs
|
namespace Bloxstrap.Dialogs
|
||||||
{
|
{
|
||||||
@ -30,10 +34,6 @@ namespace Bloxstrap.Dialogs
|
|||||||
|
|
||||||
private BootstrapperStyle? _selectedStyle;
|
private BootstrapperStyle? _selectedStyle;
|
||||||
private BootstrapperIcon? _selectedIcon;
|
private BootstrapperIcon? _selectedIcon;
|
||||||
private bool _useDiscordRichPresence = true;
|
|
||||||
private bool _hideRPCButtons = false;
|
|
||||||
private bool _useOldDeathSound = true;
|
|
||||||
private bool _useOldMouseCursor = false;
|
|
||||||
|
|
||||||
private BootstrapperStyle SelectedStyle
|
private BootstrapperStyle SelectedStyle
|
||||||
{
|
{
|
||||||
@ -68,67 +68,6 @@ namespace Bloxstrap.Dialogs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UseDiscordRichPresence
|
|
||||||
{
|
|
||||||
get => _useDiscordRichPresence;
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_useDiscordRichPresence == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_useDiscordRichPresence = value;
|
|
||||||
|
|
||||||
this.ToggleDiscordRichPresence.Checked = value;
|
|
||||||
this.ToggleRPCButtons.Enabled = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool HideRPCButtons
|
|
||||||
{
|
|
||||||
get => _hideRPCButtons;
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_hideRPCButtons == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_hideRPCButtons = value;
|
|
||||||
|
|
||||||
this.ToggleRPCButtons.Checked = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool UseOldDeathSound
|
|
||||||
{
|
|
||||||
get => _useOldDeathSound;
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_useOldDeathSound == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_useOldDeathSound = value;
|
|
||||||
|
|
||||||
this.ToggleDeathSound.Checked = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool UseOldMouseCursor
|
|
||||||
{
|
|
||||||
get => _useOldMouseCursor;
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_useOldMouseCursor == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_useOldMouseCursor = value;
|
|
||||||
|
|
||||||
this.ToggleMouseCursor.Checked = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Preferences()
|
public Preferences()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@ -142,6 +81,8 @@ namespace Bloxstrap.Dialogs
|
|||||||
{
|
{
|
||||||
this.SaveButton.Text = "Install";
|
this.SaveButton.Text = "Install";
|
||||||
this.InstallLocation.Text = Path.Combine(Program.LocalAppData, Program.ProjectName);
|
this.InstallLocation.Text = Path.Combine(Program.LocalAppData, Program.ProjectName);
|
||||||
|
this.ButtonOpenModFolder.Visible = false;
|
||||||
|
this.LabelModFolderInstall.Visible = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -158,18 +99,22 @@ namespace Bloxstrap.Dialogs
|
|||||||
this.IconSelection.Items.Add(icon.Key);
|
this.IconSelection.Items.Add(icon.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.InfoTooltip.SetToolTip(this.StyleSelection, "Choose how the bootstrapper dialog should look.\nYou can use the 'Preview' button to preview the bootstrapper look.");
|
if (!Environment.Is64BitOperatingSystem)
|
||||||
this.InfoTooltip.SetToolTip(this.IconSelection, "Choose what icon the bootstrapper should use.");
|
this.ToggleRFUEnabled.Enabled = false;
|
||||||
this.InfoTooltip.SetToolTip(this.GroupBoxInstallLocation, "Choose where Bloxstrap should install to.\nThis is useful if you typically install all your games to a separate storage drive.");
|
|
||||||
this.InfoTooltip.SetToolTip(this.ToggleDiscordRichPresence, "Choose whether to show what game you're playing on your Discord activity status.\nThis will only work when you launch a game from the website, and is not supported in the Beta App.");
|
|
||||||
this.InfoTooltip.SetToolTip(this.ToggleRPCButtons, "Choose whether the buttons to play/view game info should be hidden from activity status.");
|
|
||||||
|
|
||||||
SelectedStyle = Program.Settings.BootstrapperStyle;
|
SelectedStyle = Program.Settings.BootstrapperStyle;
|
||||||
SelectedIcon = Program.Settings.BootstrapperIcon;
|
SelectedIcon = Program.Settings.BootstrapperIcon;
|
||||||
UseDiscordRichPresence = Program.Settings.UseDiscordRichPresence;
|
|
||||||
HideRPCButtons = Program.Settings.HideRPCButtons;
|
this.ToggleCheckForUpdates.Checked = Program.Settings.CheckForUpdates;
|
||||||
UseOldDeathSound = Program.Settings.UseOldDeathSound;
|
|
||||||
UseOldMouseCursor = Program.Settings.UseOldMouseCursor;
|
this.ToggleDiscordRichPresence.Checked = Program.Settings.UseDiscordRichPresence;
|
||||||
|
this.ToggleRPCButtons.Checked = Program.Settings.HideRPCButtons;
|
||||||
|
|
||||||
|
this.ToggleRFUEnabled.Checked = Program.Settings.RFUEnabled;
|
||||||
|
this.ToggleRFUAutoclose.Checked = Program.Settings.RFUAutoclose;
|
||||||
|
|
||||||
|
this.ToggleDeathSound.Checked = Program.Settings.UseOldDeathSound;
|
||||||
|
this.ToggleMouseCursor.Checked = Program.Settings.UseOldMouseCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InstallLocationBrowseButton_Click(object sender, EventArgs e)
|
private void InstallLocationBrowseButton_Click(object sender, EventArgs e)
|
||||||
@ -239,7 +184,7 @@ namespace Bloxstrap.Dialogs
|
|||||||
{
|
{
|
||||||
Program.SettingsManager.ShouldSave = true;
|
Program.SettingsManager.ShouldSave = true;
|
||||||
|
|
||||||
if (Program.BaseDirectory != installLocation)
|
if (Program.BaseDirectory is not null && Program.BaseDirectory != installLocation)
|
||||||
{
|
{
|
||||||
Program.ShowMessageBox(MessageBoxIcon.Information, $"{Program.ProjectName} will install to the new location you've set the next time it runs.");
|
Program.ShowMessageBox(MessageBoxIcon.Information, $"{Program.ProjectName} will install to the new location you've set the next time it runs.");
|
||||||
|
|
||||||
@ -262,18 +207,12 @@ namespace Bloxstrap.Dialogs
|
|||||||
|
|
||||||
Program.Settings.BootstrapperStyle = SelectedStyle;
|
Program.Settings.BootstrapperStyle = SelectedStyle;
|
||||||
Program.Settings.BootstrapperIcon = SelectedIcon;
|
Program.Settings.BootstrapperIcon = SelectedIcon;
|
||||||
Program.Settings.UseDiscordRichPresence = UseDiscordRichPresence;
|
|
||||||
Program.Settings.HideRPCButtons = HideRPCButtons;
|
|
||||||
Program.Settings.UseOldDeathSound = UseOldDeathSound;
|
|
||||||
Program.Settings.UseOldMouseCursor = UseOldMouseCursor;
|
|
||||||
|
|
||||||
this.Close();
|
this.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreviewButton_Click(object sender, EventArgs e)
|
private void PreviewButton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
// small hack to get the icon to show in the preview without saving to settings
|
|
||||||
BootstrapperIcon savedIcon = Program.Settings.BootstrapperIcon;
|
|
||||||
Program.Settings.BootstrapperIcon = SelectedIcon;
|
Program.Settings.BootstrapperIcon = SelectedIcon;
|
||||||
|
|
||||||
this.Visible = false;
|
this.Visible = false;
|
||||||
@ -301,29 +240,57 @@ namespace Bloxstrap.Dialogs
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Program.Settings.BootstrapperIcon = savedIcon;
|
|
||||||
|
|
||||||
this.Visible = true;
|
this.Visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleDiscordRichPresence_CheckedChanged(object sender, EventArgs e)
|
private void ToggleDiscordRichPresence_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
UseDiscordRichPresence = this.ToggleDiscordRichPresence.Checked;
|
Program.Settings.UseDiscordRichPresence = this.ToggleRPCButtons.Enabled = this.ToggleDiscordRichPresence.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleRPCButtons_CheckedChanged(object sender, EventArgs e)
|
private void ToggleRPCButtons_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
HideRPCButtons = this.ToggleRPCButtons.Checked;
|
Program.Settings.HideRPCButtons = this.ToggleRPCButtons.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleRFUEnabled_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Program.Settings.RFUEnabled = this.ToggleRFUAutoclose.Enabled = this.ToggleRFUEnabled.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleRFUAutoclose_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Program.Settings.RFUAutoclose = this.ToggleRFUAutoclose.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleDeathSound_CheckedChanged(object sender, EventArgs e)
|
private void ToggleDeathSound_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
UseOldDeathSound = this.ToggleDeathSound.Checked;
|
Program.Settings.UseOldDeathSound = this.ToggleDeathSound.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleMouseCursor_CheckedChanged(object sender, EventArgs e)
|
private void ToggleMouseCursor_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
UseOldMouseCursor = this.ToggleMouseCursor.Checked;
|
Program.Settings.UseOldMouseCursor = this.ToggleMouseCursor.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleCheckForUpdates_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Program.Settings.CheckForUpdates = this.ToggleCheckForUpdates.Checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RFUWebsite_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
|
{
|
||||||
|
Utilities.OpenWebsite($"https://github.com/{RbxFpsUnlocker.ProjectRepository}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ButtonOpenModFolder_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Process.Start("explorer.exe", Directories.Modifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Preferences_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.Activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,10 +57,10 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<metadata name="InstallLocationBrowseDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>17, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="InfoTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="InfoTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>222, 17</value>
|
<value>222, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="InstallLocationBrowseDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
</root>
|
</root>
|
28
Bloxstrap/Helpers/Directories.cs
Normal file
28
Bloxstrap/Helpers/Directories.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Bloxstrap.Helpers
|
||||||
|
{
|
||||||
|
internal class Directories
|
||||||
|
{
|
||||||
|
public static string Base { get; private set; } = "";
|
||||||
|
public static string Downloads { 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 App { get; private set; } = "";
|
||||||
|
|
||||||
|
public static bool Initialized { get => String.IsNullOrEmpty(Base); }
|
||||||
|
|
||||||
|
public static void Initialize(string baseDirectory)
|
||||||
|
{
|
||||||
|
Base = baseDirectory;
|
||||||
|
Downloads = Path.Combine(Base, "Downloads");
|
||||||
|
Integrations = Path.Combine(Base, "Integrations");
|
||||||
|
Versions = Path.Combine(Base, "Versions");
|
||||||
|
Modifications = Path.Combine(Base, "Modifications");
|
||||||
|
|
||||||
|
App = Path.Combine(Base, $"{Program.ProjectName}.exe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,39 +1,35 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json.Linq;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
|
|
||||||
namespace Bloxstrap.Helpers
|
namespace Bloxstrap.Helpers.Integrations
|
||||||
{
|
{
|
||||||
internal class DiscordRichPresence : IDisposable
|
internal class DiscordRichPresence : IDisposable
|
||||||
{
|
{
|
||||||
readonly DiscordRpcClient RichPresence = new("1005469189907173486");
|
readonly DiscordRpcClient RichPresence = new("1005469189907173486");
|
||||||
|
|
||||||
public async Task<bool> SetPresence(string placeId)
|
public async Task<bool> SetPresence(string placeId)
|
||||||
{
|
{
|
||||||
string placeName;
|
string placeName;
|
||||||
string placeThumbnail;
|
string placeThumbnail;
|
||||||
string creatorName;
|
string creatorName;
|
||||||
|
|
||||||
// null checking could probably be a lot more concrete here
|
// null checking could probably be a lot more concrete here
|
||||||
using (HttpClient client = new())
|
JObject placeInfo = await Utilities.GetJson($"https://economy.roblox.com/v2/assets/{placeId}/details");
|
||||||
{
|
|
||||||
JObject placeInfo = await Utilities.GetJson($"https://economy.roblox.com/v2/assets/{placeId}/details");
|
|
||||||
|
|
||||||
placeName = placeInfo["Name"].Value<string>();
|
placeName = placeInfo["Name"].Value<string>();
|
||||||
creatorName = placeInfo["Creator"]["Name"].Value<string>();
|
creatorName = placeInfo["Creator"]["Name"].Value<string>();
|
||||||
|
|
||||||
JObject thumbnailInfo = await Utilities.GetJson($"https://thumbnails.roblox.com/v1/places/gameicons?placeIds={placeId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false");
|
JObject thumbnailInfo = await Utilities.GetJson($"https://thumbnails.roblox.com/v1/places/gameicons?placeIds={placeId}&returnPolicy=PlaceHolder&size=512x512&format=Png&isCircular=false");
|
||||||
|
|
||||||
if (thumbnailInfo["data"] is null)
|
if (thumbnailInfo["data"] is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
placeThumbnail = thumbnailInfo["data"][0]["imageUrl"].Value<string>();
|
placeThumbnail = thumbnailInfo["data"][0]["imageUrl"].Value<string>();
|
||||||
}
|
|
||||||
|
|
||||||
DiscordRPC.Button[]? buttons = null;
|
DiscordRPC.Button[]? buttons = null;
|
||||||
|
|
||||||
if (!Program.Settings.HideRPCButtons)
|
if (!Program.Settings.HideRPCButtons)
|
||||||
{
|
{
|
||||||
buttons = new DiscordRPC.Button[]
|
buttons = new DiscordRPC.Button[]
|
||||||
{
|
{
|
||||||
new DiscordRPC.Button()
|
new DiscordRPC.Button()
|
||||||
@ -57,16 +53,14 @@ namespace Bloxstrap.Helpers
|
|||||||
Details = placeName,
|
Details = placeName,
|
||||||
State = $"by {creatorName}",
|
State = $"by {creatorName}",
|
||||||
Timestamps = new Timestamps() { Start = DateTime.UtcNow },
|
Timestamps = new Timestamps() { Start = DateTime.UtcNow },
|
||||||
|
Buttons = buttons,
|
||||||
Assets = new Assets()
|
Assets = new Assets()
|
||||||
{
|
{
|
||||||
LargeImageKey = placeThumbnail,
|
LargeImageKey = placeThumbnail,
|
||||||
LargeImageText = placeName,
|
LargeImageText = placeName,
|
||||||
SmallImageKey = "bloxstrap",
|
SmallImageKey = "roblox",
|
||||||
SmallImageText = "Rich Presence provided by Bloxstrap"
|
SmallImageText = "Roblox"
|
||||||
},
|
}
|
||||||
|
|
||||||
Buttons = buttons
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
95
Bloxstrap/Helpers/Integrations/RbxFpsUnlocker.cs
Normal file
95
Bloxstrap/Helpers/Integrations/RbxFpsUnlocker.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Bloxstrap.Helpers.Integrations
|
||||||
|
{
|
||||||
|
internal class RbxFpsUnlocker
|
||||||
|
{
|
||||||
|
public const string ProjectRepository = "axstin/rbxfpsunlocker";
|
||||||
|
|
||||||
|
// default settings but with QuickStart set to true and CheckForUpdates set to false
|
||||||
|
private static readonly string Settings =
|
||||||
|
"UnlockClient=true\n" +
|
||||||
|
"UnlockStudio=false\n" +
|
||||||
|
"FPSCapValues=[30.000000, 60.000000, 75.000000, 120.000000, 144.000000, 165.000000, 240.000000, 360.000000]\n" +
|
||||||
|
"FPSCapSelection=0\n" +
|
||||||
|
"FPSCap=0.000000\n" +
|
||||||
|
"CheckForUpdates=false\n" +
|
||||||
|
"NonBlockingErrors=true\n" +
|
||||||
|
"SilentErrors=false\n" +
|
||||||
|
"QuickStart=true\n";
|
||||||
|
|
||||||
|
public static async Task CheckInstall()
|
||||||
|
{
|
||||||
|
if (Program.BaseDirectory is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string folderLocation = Path.Combine(Program.BaseDirectory, "Integrations", "rbxfpsunlocker");
|
||||||
|
string fileLocation = Path.Combine(folderLocation, "rbxfpsunlocker.exe");
|
||||||
|
string settingsLocation = Path.Combine(folderLocation, "settings");
|
||||||
|
|
||||||
|
if (!Program.Settings.RFUEnabled)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(folderLocation))
|
||||||
|
{
|
||||||
|
Directory.Delete(folderLocation, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime lastReleasePublish;
|
||||||
|
string downloadUrl;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JObject releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{ProjectRepository}/releases/latest");
|
||||||
|
|
||||||
|
// so... rbxfpsunlocker does not actually have any version info for the executable
|
||||||
|
// meaning the best way we can check for a new version is comparing time last download to time last release published
|
||||||
|
lastReleasePublish = DateTime.Parse(releaseInfo["created_at"].Value<string>());
|
||||||
|
downloadUrl = releaseInfo["assets"][0]["browser_download_url"].Value<string>();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Failed to fetch latest version info! ({ex.Message})");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(folderLocation);
|
||||||
|
|
||||||
|
if (File.Exists(fileLocation))
|
||||||
|
{
|
||||||
|
DateTime lastDownload = File.GetCreationTimeUtc(fileLocation);
|
||||||
|
|
||||||
|
// no new release published, return
|
||||||
|
if (lastDownload > lastReleasePublish)
|
||||||
|
return;
|
||||||
|
|
||||||
|
File.Delete(fileLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine("Installing/Updating rbxfpsunlocker...");
|
||||||
|
|
||||||
|
using (HttpClient client = new())
|
||||||
|
{
|
||||||
|
byte[] bytes = await client.GetByteArrayAsync(downloadUrl);
|
||||||
|
|
||||||
|
using (MemoryStream zipStream = new MemoryStream(bytes))
|
||||||
|
{
|
||||||
|
ZipArchive zip = new ZipArchive(zipStream);
|
||||||
|
zip.ExtractToDirectory(folderLocation, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(settingsLocation))
|
||||||
|
{
|
||||||
|
await File.WriteAllTextAsync(settingsLocation, Settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Web;
|
using System.Text;
|
||||||
|
using System.Web;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace Bloxstrap.Helpers
|
namespace Bloxstrap.Helpers
|
||||||
@ -9,11 +10,11 @@ namespace Bloxstrap.Helpers
|
|||||||
private static readonly IReadOnlyDictionary<string, string> UriKeyArgMap = new Dictionary<string, string>()
|
private static readonly IReadOnlyDictionary<string, string> UriKeyArgMap = new Dictionary<string, string>()
|
||||||
{
|
{
|
||||||
// excluding roblox-player, browsertrackerid and channel
|
// excluding roblox-player, browsertrackerid and channel
|
||||||
{ "launchmode", "--" },
|
{ "launchmode", "--" },
|
||||||
{ "gameinfo", "-t " },
|
{ "gameinfo", "-t " },
|
||||||
{ "placelauncherurl", "-j "},
|
{ "placelauncherurl", "-j "},
|
||||||
// { "launchtime", "--launchtime=" }, we'll set this when launching the game client
|
// { "launchtime", "--launchtime=" }, we'll set this when launching the game client
|
||||||
{ "robloxLocale", "--rloc " },
|
{ "robloxLocale", "--rloc " },
|
||||||
{ "gameLocale", "--gloc " },
|
{ "gameLocale", "--gloc " },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ namespace Bloxstrap.Helpers
|
|||||||
string[] keyvalPair;
|
string[] keyvalPair;
|
||||||
string key;
|
string key;
|
||||||
string val;
|
string val;
|
||||||
string commandLine = "";
|
StringBuilder commandLine = new();
|
||||||
|
|
||||||
foreach (var parameter in protocol.Split('+'))
|
foreach (var parameter in protocol.Split('+'))
|
||||||
{
|
{
|
||||||
@ -39,10 +40,10 @@ namespace Bloxstrap.Helpers
|
|||||||
if (key == "placelauncherurl")
|
if (key == "placelauncherurl")
|
||||||
val = HttpUtility.UrlDecode(val).Replace("browserTrackerId", "lol");
|
val = HttpUtility.UrlDecode(val).Replace("browserTrackerId", "lol");
|
||||||
|
|
||||||
commandLine += UriKeyArgMap[key] + val + " ";
|
commandLine.Append(UriKeyArgMap[key] + val + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return commandLine;
|
return commandLine.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Register(string key, string name, string handler)
|
public static void Register(string key, string name, string handler)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// https://github.com/MaximumADHD/Roblox-Studio-Mod-Manager/blob/main/ProjectSrc/Bootstrapper/FileManifest.cs
|
// https://github.com/MaximumADHD/Roblox-Studio-Mod-Manager/blob/main/ProjectSrc/Bootstrapper/FileManifest.cs
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace Bloxstrap.Helpers.RSMM
|
namespace Bloxstrap.Helpers.RSMM
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// https://github.com/MaximumADHD/Roblox-Studio-Mod-Manager/blob/main/ProjectSrc/Bootstrapper/PackageManifest.cs
|
// https://github.com/MaximumADHD/Roblox-Studio-Mod-Manager/blob/main/ProjectSrc/Bootstrapper/PackageManifest.cs
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace Bloxstrap.Helpers.RSMM
|
namespace Bloxstrap.Helpers.RSMM
|
||||||
{
|
{
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace Bloxstrap.Helpers
|
namespace Bloxstrap.Helpers
|
||||||
{
|
{
|
||||||
public class UpdateChecker
|
public class Updater
|
||||||
{
|
{
|
||||||
public static void CheckInstalledVersion()
|
public static bool CheckInstalledVersion()
|
||||||
{
|
{
|
||||||
if (Environment.ProcessPath is null || !File.Exists(Program.FilePath))
|
if (Environment.ProcessPath is null || !File.Exists(Directories.App) || Environment.ProcessPath == Directories.App)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// if downloaded version doesn't match, replace installed version with downloaded version
|
// if downloaded version doesn't match, replace installed version with downloaded version
|
||||||
FileVersionInfo currentVersionInfo = FileVersionInfo.GetVersionInfo(Environment.ProcessPath);
|
FileVersionInfo currentVersionInfo = FileVersionInfo.GetVersionInfo(Environment.ProcessPath);
|
||||||
FileVersionInfo installedVersionInfo = FileVersionInfo.GetVersionInfo(Program.FilePath);
|
FileVersionInfo installedVersionInfo = FileVersionInfo.GetVersionInfo(Directories.App);
|
||||||
|
|
||||||
if (installedVersionInfo.ProductVersion != currentVersionInfo.ProductVersion)
|
if (installedVersionInfo.ProductVersion != currentVersionInfo.ProductVersion)
|
||||||
{
|
{
|
||||||
@ -25,10 +27,13 @@ namespace Bloxstrap.Helpers
|
|||||||
|
|
||||||
if (result == DialogResult.Yes)
|
if (result == DialogResult.Yes)
|
||||||
{
|
{
|
||||||
File.Delete(Program.FilePath);
|
File.Delete(Directories.App);
|
||||||
File.Copy(Environment.ProcessPath, Program.FilePath);
|
File.Copy(Environment.ProcessPath, Directories.App);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Check()
|
public static async Task Check()
|
||||||
@ -36,6 +41,12 @@ namespace Bloxstrap.Helpers
|
|||||||
if (Environment.ProcessPath is null)
|
if (Environment.ProcessPath is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!Program.IsFirstRun && CheckInstalledVersion())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!Program.Settings.CheckForUpdates)
|
||||||
|
return;
|
||||||
|
|
||||||
FileVersionInfo currentVersionInfo = FileVersionInfo.GetVersionInfo(Environment.ProcessPath);
|
FileVersionInfo currentVersionInfo = FileVersionInfo.GetVersionInfo(Environment.ProcessPath);
|
||||||
string currentVersion = $"Bloxstrap v{currentVersionInfo.ProductVersion}";
|
string currentVersion = $"Bloxstrap v{currentVersionInfo.ProductVersion}";
|
||||||
string latestVersion;
|
string latestVersion;
|
||||||
@ -67,7 +78,7 @@ namespace Bloxstrap.Helpers
|
|||||||
|
|
||||||
if (result == DialogResult.Yes)
|
if (result == DialogResult.Yes)
|
||||||
{
|
{
|
||||||
Process.Start(new ProcessStartInfo { FileName = $"https://github.com/{Program.ProjectRepository}/releases/latest", UseShellExecute = true });
|
Utilities.OpenWebsite($"https://github.com/{Program.ProjectRepository}/releases/latest");
|
||||||
Program.Exit();
|
Program.Exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,7 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@ -7,6 +10,11 @@ namespace Bloxstrap.Helpers
|
|||||||
{
|
{
|
||||||
public class Utilities
|
public class Utilities
|
||||||
{
|
{
|
||||||
|
public static void OpenWebsite(string website)
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true });
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<JObject> GetJson(string url)
|
public static async Task<JObject> GetJson(string url)
|
||||||
{
|
{
|
||||||
using (HttpClient client = new())
|
using (HttpClient client = new())
|
||||||
@ -18,7 +26,7 @@ namespace Bloxstrap.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string CalculateMD5(string filename)
|
public static string MD5File(string filename)
|
||||||
{
|
{
|
||||||
using (MD5 md5 = MD5.Create())
|
using (MD5 md5 = MD5.Create())
|
||||||
{
|
{
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
using Bloxstrap.Enums;
|
using Bloxstrap.Enums;
|
||||||
|
|
||||||
namespace Bloxstrap
|
namespace Bloxstrap
|
||||||
@ -8,10 +10,16 @@ namespace Bloxstrap
|
|||||||
{
|
{
|
||||||
public string VersionGuid { get; set; }
|
public string VersionGuid { get; set; }
|
||||||
|
|
||||||
|
public bool CheckForUpdates { get; set; } = true;
|
||||||
|
|
||||||
public BootstrapperStyle BootstrapperStyle { get; set; } = BootstrapperStyle.ProgressDialog;
|
public BootstrapperStyle BootstrapperStyle { get; set; } = BootstrapperStyle.ProgressDialog;
|
||||||
public BootstrapperIcon BootstrapperIcon { get; set; } = BootstrapperIcon.IconBloxstrap;
|
public BootstrapperIcon BootstrapperIcon { get; set; } = BootstrapperIcon.IconBloxstrap;
|
||||||
|
|
||||||
public bool UseDiscordRichPresence { get; set; } = true;
|
public bool UseDiscordRichPresence { get; set; } = true;
|
||||||
public bool HideRPCButtons { get; set; } = false;
|
public bool HideRPCButtons { get; set; } = false;
|
||||||
|
public bool RFUEnabled { get; set; } = false;
|
||||||
|
public bool RFUAutoclose { get; set; } = false;
|
||||||
|
|
||||||
public bool UseOldDeathSound { get; set; } = true;
|
public bool UseOldDeathSound { get; set; } = true;
|
||||||
public bool UseOldMouseCursor { get; set; } = false;
|
public bool UseOldMouseCursor { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user