Minor restructuring

This commit is contained in:
pizzaboxer 2023-06-26 22:33:15 +01:00
parent 28bcf57dff
commit e7fd0b9642
No known key found for this signature in database
GPG Key ID: 59D4A1DBAD0F2BA8
15 changed files with 256 additions and 285 deletions

View File

@ -15,10 +15,10 @@ using Microsoft.Win32;
using Bloxstrap.Extensions; using Bloxstrap.Extensions;
using Bloxstrap.Models; using Bloxstrap.Models;
using Bloxstrap.Singletons;
using Bloxstrap.UI.BootstrapperDialogs; using Bloxstrap.UI.BootstrapperDialogs;
using Bloxstrap.UI.Menu.Views; using Bloxstrap.UI.Menu.Views;
using Bloxstrap.Utility;
namespace Bloxstrap namespace Bloxstrap
{ {
/// <summary> /// <summary>

View File

@ -256,7 +256,7 @@ namespace Bloxstrap
if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch)
{ {
Utilities.OpenWebsite("https://www.roblox.com/games"); Utilities.ShellExecute("https://www.roblox.com/games");
Dialog?.CloseBootstrapper(); Dialog?.CloseBootstrapper();
return; return;
} }
@ -562,7 +562,7 @@ namespace Bloxstrap
private async Task CheckForUpdates() private async Task CheckForUpdates()
{ {
// don't update if there's another instance running (likely running in the background) // don't update if there's another instance running (likely running in the background)
if (Utilities.GetProcessCount(App.ProjectName) > 1) if (Process.GetProcessesByName(App.ProjectName).Count() > 1)
{ {
App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check");
return; return;
@ -616,7 +616,7 @@ namespace Bloxstrap
private void Uninstall() private void Uninstall()
{ {
// prompt to shutdown roblox if its currently running // prompt to shutdown roblox if its currently running
if (Utilities.CheckIfRobloxRunning()) if (Process.GetProcessesByName(App.RobloxAppName).Any())
{ {
App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances");
@ -1004,7 +1004,7 @@ namespace Bloxstrap
if (File.Exists(fileVersionFolder)) if (File.Exists(fileVersionFolder))
{ {
if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) if (Utility.MD5Hash.FromFile(fileModFolder) == Utility.MD5Hash.FromFile(fileVersionFolder))
continue; continue;
} }
@ -1072,7 +1072,7 @@ namespace Bloxstrap
await File.WriteAllBytesAsync(modFolderLocation, binaryData); await File.WriteAllBytesAsync(modFolderLocation, binaryData);
} }
} }
else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) else if (File.Exists(modFolderLocation) && Utility.MD5Hash.FromFile(modFolderLocation) == Utility.MD5Hash.FromBytes(binaryData))
{ {
File.Delete(modFolderLocation); File.Delete(modFolderLocation);
} }
@ -1091,7 +1091,8 @@ namespace Bloxstrap
{ {
FileInfo file = new(packageLocation); FileInfo file = new(packageLocation);
string calculatedMD5 = Utilities.MD5File(packageLocation); string calculatedMD5 = Utility.MD5Hash.FromFile(packageLocation);
if (calculatedMD5 != package.Signature) if (calculatedMD5 != package.Signature)
{ {
App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading...");

View File

@ -1,10 +1,8 @@
using Newtonsoft.Json.Linq; using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
namespace Bloxstrap.Singletons namespace Bloxstrap
{ {
public class FastFlagManager : JsonManager<Dictionary<string, object>> public class FastFlagManager : JsonManager<Dictionary<string, object>>
{ {
@ -103,18 +101,18 @@ namespace Bloxstrap.Singletons
// this will set the flag to the corresponding value if the condition is true // this will set the flag to the corresponding value if the condition is true
// if the condition is not true, the flag will be erased // if the condition is not true, the flag will be erased
public void SetValueIf(bool condition, string key, object? value) public void SetValueIf(bool condition, string key, object? value)
{ {
if (condition) if (condition)
SetValue(key, value); SetValue(key, value);
else if (GetValue(key) is not null) else if (GetValue(key) is not null)
SetValue(key, null); SetValue(key, null);
} }
public void SetValueOnce(string key, object? value) public void SetValueOnce(string key, object? value)
{ {
if (GetValue(key) is null) if (GetValue(key) is null)
SetValue(key, value); SetValue(key, value);
} }
// this returns null if the fflag doesn't exist // this returns null if the fflag doesn't exist

View File

@ -2,7 +2,7 @@
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
namespace Bloxstrap.Singletons namespace Bloxstrap
{ {
public class JsonManager<T> where T : new() public class JsonManager<T> where T : new()
{ {

View File

@ -5,7 +5,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
namespace Bloxstrap.Singletons namespace Bloxstrap
{ {
// https://stackoverflow.com/a/53873141/11852173 // https://stackoverflow.com/a/53873141/11852173
// TODO - this kind of sucks // TODO - this kind of sucks

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using Bloxstrap.Extensions; using Bloxstrap.Extensions;
using Bloxstrap.Utility;
namespace Bloxstrap.UI.BootstrapperDialogs.WinForms namespace Bloxstrap.UI.BootstrapperDialogs.WinForms
{ {

View File

@ -1,13 +1,10 @@
using System; using System.Collections.Generic;
using System.Collections.Generic; using System.ComponentModel;
using System.IO; using System.IO;
using System.Windows.Input; using System.Windows.Input;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Bloxstrap.Singletons;
using System.ComponentModel;
namespace Bloxstrap.UI.Menu.ViewModels namespace Bloxstrap.UI.Menu.ViewModels
{ {
public class FastFlagsViewModel : INotifyPropertyChanged public class FastFlagsViewModel : INotifyPropertyChanged
@ -17,7 +14,7 @@ namespace Bloxstrap.UI.Menu.ViewModels
public ICommand OpenClientSettingsCommand => new RelayCommand(OpenClientSettings); public ICommand OpenClientSettingsCommand => new RelayCommand(OpenClientSettings);
private void OpenClientSettings() => Utilities.OpenWebsite(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); private void OpenClientSettings() => Utilities.ShellExecute(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json"));
public int FramerateLimit public int FramerateLimit
{ {
@ -40,19 +37,19 @@ namespace Bloxstrap.UI.Menu.ViewModels
return "Automatic"; return "Automatic";
} }
set set
{ {
foreach (var mode in RenderingModes) foreach (var mode in RenderingModes)
{ {
if (mode.Key != "Automatic") if (mode.Key != "Automatic")
App.FastFlags.SetValue(mode.Value, null); App.FastFlags.SetValue(mode.Value, null);
} }
if (value == "Automatic") if (value == "Automatic")
return; return;
App.FastFlags.SetValue(RenderingModes[value], "True"); App.FastFlags.SetValue(RenderingModes[value], "True");
App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True"); App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True");
} }
} }

View File

@ -14,7 +14,7 @@ namespace Bloxstrap.UI.Menu.ViewModels
if (location is null) if (location is null)
return; return;
Utilities.OpenWebsite(location); Utilities.ShellExecute(location);
} }
} }
} }

View File

@ -78,7 +78,7 @@ namespace Bloxstrap
if (isAutoUpgrade) if (isAutoUpgrade)
{ {
EventHandler ReleaseNotesLauncher = new((_, _) => Utilities.OpenWebsite($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")); EventHandler ReleaseNotesLauncher = new((_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}"));
App.Notification.BalloonTipTitle = $"Bloxstrap has been upgraded to v{currentVersionInfo.ProductVersion}"; App.Notification.BalloonTipTitle = $"Bloxstrap has been upgraded to v{currentVersionInfo.ProductVersion}";
App.Notification.BalloonTipText = "Click here to see what's new in this version"; App.Notification.BalloonTipText = "Click here to see what's new in this version";

View File

@ -10,11 +10,6 @@ namespace Bloxstrap
{ {
static class Utilities static class Utilities
{ {
public static bool IsDirectoryEmpty(string path)
{
return !Directory.EnumerateFileSystemEntries(path).Any();
}
public static long GetFreeDiskSpace(string path) public static long GetFreeDiskSpace(string path)
{ {
foreach (DriveInfo drive in DriveInfo.GetDrives()) foreach (DriveInfo drive in DriveInfo.GetDrives())
@ -26,24 +21,7 @@ namespace Bloxstrap
return -1; return -1;
} }
public static int GetProcessCount(string processName, bool log = true) public static void ShellExecute(string website) => Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true });
{
if (log)
App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Checking if '{processName}' is running...");
Process[] processes = Process.GetProcessesByName(processName);
if (log)
App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Found {processes.Length} process(es) running for '{processName}'");
return processes.Length;
}
public static bool CheckIfProcessRunning(string processName, bool log = true) => GetProcessCount(processName, log) >= 1;
public static bool CheckIfRobloxRunning(bool log = true) => CheckIfProcessRunning("RobloxPlayerBeta", log);
public static void OpenWebsite(string website) => Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true });
public static async Task<T?> GetJson<T>(string url) public static async Task<T?> GetJson<T>(string url)
{ {
@ -61,41 +39,5 @@ namespace Bloxstrap
return default; return default;
} }
} }
public static string MD5File(string filename)
{
using (MD5 md5 = MD5.Create())
{
using (FileStream stream = File.OpenRead(filename))
{
byte[] hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
public static string MD5Data(byte[] data)
{
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(data);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
// quick and hacky way of getting a value from any key/value pair formatted list
// (command line args, uri params, etc)
public static string? GetKeyValue(string subject, string key, char delimiter)
{
if (subject.LastIndexOf(key) == -1)
return null;
string substr = subject.Substring(subject.LastIndexOf(key) + key.Length);
if (!substr.Contains(delimiter))
return null;
return substr.Split(delimiter)[0];
}
} }
} }

View File

@ -1,102 +1,102 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Bloxstrap.Tools namespace Bloxstrap.Tools
{ {
// https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e // https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e
public sealed class AsyncMutex : IAsyncDisposable public sealed class AsyncMutex : IAsyncDisposable
{ {
private readonly string _name; private readonly string _name;
private Task? _mutexTask; private Task? _mutexTask;
private ManualResetEventSlim? _releaseEvent; private ManualResetEventSlim? _releaseEvent;
private CancellationTokenSource? _cancellationTokenSource; private CancellationTokenSource? _cancellationTokenSource;
public AsyncMutex(string name) public AsyncMutex(string name)
{ {
_name = name; _name = name;
} }
public Task AcquireAsync(CancellationToken cancellationToken) public Task AcquireAsync(CancellationToken cancellationToken)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
TaskCompletionSource taskCompletionSource = new(); TaskCompletionSource taskCompletionSource = new();
_releaseEvent = new ManualResetEventSlim(); _releaseEvent = new ManualResetEventSlim();
_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
// Putting all mutex manipulation in its own task as it doesn't work in async contexts // Putting all mutex manipulation in its own task as it doesn't work in async contexts
// Note: this task should not throw. // Note: this task should not throw.
_mutexTask = Task.Factory.StartNew( _mutexTask = Task.Factory.StartNew(
state => state =>
{ {
try try
{ {
CancellationToken cancellationToken = _cancellationTokenSource.Token; CancellationToken cancellationToken = _cancellationTokenSource.Token;
using var mutex = new Mutex(false, _name); using var mutex = new Mutex(false, _name);
try try
{ {
// Wait for either the mutex to be acquired, or cancellation // Wait for either the mutex to be acquired, or cancellation
if (WaitHandle.WaitAny(new[] { mutex, cancellationToken.WaitHandle }) != 0) if (WaitHandle.WaitAny(new[] { mutex, cancellationToken.WaitHandle }) != 0)
{ {
taskCompletionSource.SetCanceled(cancellationToken); taskCompletionSource.SetCanceled(cancellationToken);
return; return;
} }
} }
catch (AbandonedMutexException) catch (AbandonedMutexException)
{ {
// Abandoned by another process, we acquired it. // Abandoned by another process, we acquired it.
} }
taskCompletionSource.SetResult(); taskCompletionSource.SetResult();
// Wait until the release call // Wait until the release call
_releaseEvent.Wait(); _releaseEvent.Wait();
mutex.ReleaseMutex(); mutex.ReleaseMutex();
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
taskCompletionSource.TrySetCanceled(cancellationToken); taskCompletionSource.TrySetCanceled(cancellationToken);
} }
catch (Exception ex) catch (Exception ex)
{ {
taskCompletionSource.TrySetException(ex); taskCompletionSource.TrySetException(ex);
} }
}, },
state: null, state: null,
cancellationToken, cancellationToken,
TaskCreationOptions.LongRunning, TaskCreationOptions.LongRunning,
TaskScheduler.Default); TaskScheduler.Default);
return taskCompletionSource.Task; return taskCompletionSource.Task;
} }
public async Task ReleaseAsync() public async Task ReleaseAsync()
{ {
_releaseEvent?.Set(); _releaseEvent?.Set();
if (_mutexTask != null) if (_mutexTask != null)
{ {
await _mutexTask; await _mutexTask;
} }
} }
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()
{ {
// Ensure the mutex task stops waiting for any acquire // Ensure the mutex task stops waiting for any acquire
_cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Cancel();
// Ensure the mutex is released // Ensure the mutex is released
await ReleaseAsync(); await ReleaseAsync();
_releaseEvent?.Dispose(); _releaseEvent?.Dispose();
_cancellationTokenSource?.Dispose(); _cancellationTokenSource?.Dispose();
} }
} }
} }

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Bloxstrap.Utility
{
public static class MD5Hash
{
public static string FromFile(string filename)
{
using (MD5 md5 = MD5.Create())
{
using (FileStream stream = File.OpenRead(filename))
{
byte[] hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
public static string FromBytes(byte[] data)
{
using (MD5 md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(data);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
}
}

View File

@ -4,8 +4,8 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Bloxstrap namespace Bloxstrap.Utility
{ {
static class NativeMethods static class NativeMethods
{ {

View File

@ -1,47 +1,47 @@
/* /*
* Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs) * Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs)
* MIT License * MIT License
* Copyright (c) 2015-present MaximumADHD * Copyright (c) 2015-present MaximumADHD
*/ */
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Bloxstrap.Tools namespace Bloxstrap.Tools
{ {
public class SystemEvent : EventWaitHandle public class SystemEvent : EventWaitHandle
{ {
public string Name { get; private set; } public string Name { get; private set; }
public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name) public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name)
{ {
if (init) if (init)
Reset(); Reset();
else else
Set(); Set();
Name = name; Name = name;
} }
public override string ToString() public override string ToString()
{ {
return Name; return Name;
} }
public Task<bool> WaitForEvent() public Task<bool> WaitForEvent()
{ {
return Task.Run(WaitOne); return Task.Run(WaitOne);
} }
public Task<bool> WaitForEvent(TimeSpan timeout, bool exitContext = false) public Task<bool> WaitForEvent(TimeSpan timeout, bool exitContext = false)
{ {
return Task.Run(() => WaitOne(timeout, exitContext)); return Task.Run(() => WaitOne(timeout, exitContext));
} }
public Task<bool> WaitForEvent(int millisecondsTimeout, bool exitContext = false) public Task<bool> WaitForEvent(int millisecondsTimeout, bool exitContext = false)
{ {
return Task.Run(() => WaitOne(millisecondsTimeout, exitContext)); return Task.Run(() => WaitOne(millisecondsTimeout, exitContext));
} }
} }
} }

View File

@ -1,34 +1,31 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
namespace Bloxstrap namespace Bloxstrap.Utility
{ {
public static class WindowScaling public static class WindowScaling
{ {
public static double GetFactor() public static double ScaleFactor => Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth;
{
return Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; public static int GetScaledNumber(int number)
} {
return (int)Math.Ceiling(number * ScaleFactor);
public static int GetScaledNumber(int number) }
{
return (int)Math.Ceiling(number * GetFactor()); public static System.Drawing.Size GetScaledSize(System.Drawing.Size size)
} {
return new System.Drawing.Size(GetScaledNumber(size.Width), GetScaledNumber(size.Height));
public static System.Drawing.Size GetScaledSize(System.Drawing.Size size) }
{
return new System.Drawing.Size(GetScaledNumber(size.Width), GetScaledNumber(size.Height)); public static System.Drawing.Point GetScaledPoint(System.Drawing.Point point)
} {
return new System.Drawing.Point(GetScaledNumber(point.X), GetScaledNumber(point.Y));
public static System.Drawing.Point GetScaledPoint(System.Drawing.Point point) }
{
return new System.Drawing.Point(GetScaledNumber(point.X), GetScaledNumber(point.Y)); public static Padding GetScaledPadding(Padding padding)
} {
return new Padding(GetScaledNumber(padding.Left), GetScaledNumber(padding.Top), GetScaledNumber(padding.Right), GetScaledNumber(padding.Bottom));
public static Padding GetScaledPadding(Padding padding) }
{ }
return new Padding(GetScaledNumber(padding.Left), GetScaledNumber(padding.Top), GetScaledNumber(padding.Right), GetScaledNumber(padding.Bottom)); }
}
}
}