Add support for multi-instance launching (#72)

didnt fully look into handling mutex ownership and it'll probably screw up when the first roblox window is closed so hopefully this works fine 👍
This commit is contained in:
pizzaboxer 2023-02-03 22:00:55 +00:00
parent abd56959f2
commit 7eb9aa88f2
4 changed files with 66 additions and 44 deletions

View File

@ -5,6 +5,7 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows; using System.Windows;
@ -232,59 +233,64 @@ namespace Bloxstrap
LaunchCommandLine += " -startEvent " + startEventName; LaunchCommandLine += " -startEvent " + startEventName;
bool shouldWait = false;
Process gameClient = Process.Start(Path.Combine(VersionFolder, "RobloxPlayerBeta.exe"), LaunchCommandLine);
Process? rbxFpsUnlocker = null;
DiscordRichPresence? richPresence = null;
Mutex? singletonMutex = null;
using (SystemEvent startEvent = new(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(); bool startEventFired = await startEvent.WaitForEvent();
startEvent.Close(); startEvent.Close();
if (!startEventFired) if (!startEventFired)
return; return;
if (App.Settings.RFUEnabled && Process.GetProcessesByName("rbxfpsunlocker").Length == 0)
{
ProcessStartInfo startInfo = new()
{
FileName = Path.Combine(Directories.Integrations, @"rbxfpsunlocker\rbxfpsunlocker.exe"),
WorkingDirectory = Path.Combine(Directories.Integrations, "rbxfpsunlocker")
};
rbxFpsUnlocker = Process.Start(startInfo);
if (App.Settings.RFUAutoclose)
shouldWait = true;
}
// event fired, wait for 3 seconds then close
await Task.Delay(3000);
// now we move onto handling rich presence
if (App.Settings.UseDiscordRichPresence)
{
richPresence = new DiscordRichPresence();
richPresence.MonitorGameActivity();
shouldWait = true;
}
if (!shouldWait)
return;
// keep bloxstrap open in the background
Dialog.CloseDialog();
await gameClient.WaitForExitAsync();
richPresence?.Dispose();
if (App.Settings.RFUAutoclose && rbxFpsUnlocker is not null)
rbxFpsUnlocker.Kill();
} }
if (App.Settings.RFUEnabled && Process.GetProcessesByName("rbxfpsunlocker").Length == 0)
{
ProcessStartInfo startInfo = new()
{
FileName = Path.Combine(Directories.Integrations, @"rbxfpsunlocker\rbxfpsunlocker.exe"),
WorkingDirectory = Path.Combine(Directories.Integrations, "rbxfpsunlocker")
};
rbxFpsUnlocker = Process.Start(startInfo);
if (App.Settings.RFUAutoclose)
shouldWait = true;
}
if (App.Settings.MultiInstanceLaunching)
{
singletonMutex = new Mutex(true, "ROBLOX_singletonMutex");
shouldWait = true;
}
// event fired, wait for 3 seconds then close
await Task.Delay(3000);
if (App.Settings.UseDiscordRichPresence)
{
richPresence = new DiscordRichPresence();
richPresence.MonitorGameActivity();
shouldWait = true;
}
if (!shouldWait)
return;
// keep bloxstrap open in the background
Dialog.CloseDialog();
await gameClient.WaitForExitAsync();
richPresence?.Dispose();
singletonMutex?.ReleaseMutex();
if (App.Settings.RFUAutoclose && rbxFpsUnlocker is not null)
rbxFpsUnlocker.Kill();
} }
public void CancelButtonClicked() public void CancelButtonClicked()

View File

@ -20,6 +20,7 @@ namespace Bloxstrap.Models
public Theme Theme { get; set; } = Theme.Default; public Theme Theme { get; set; } = Theme.Default;
public bool CheckForUpdates { get; set; } = true; public bool CheckForUpdates { get; set; } = true;
public bool CreateDesktopIcon { get; set; } = true; public bool CreateDesktopIcon { get; set; } = true;
public bool MultiInstanceLaunching { get; set; } = false;
// channel configuration // channel configuration
public string Channel { get; set; } = DeployManager.DefaultChannel; public string Channel { get; set; } = DeployManager.DefaultChannel;

View File

@ -39,6 +39,12 @@ namespace Bloxstrap.ViewModels
set => App.Settings.PromptChannelChange = value; set => App.Settings.PromptChannelChange = value;
} }
public bool MultiInstanceLaunchingEnabled
{
get => App.Settings.MultiInstanceLaunching;
set => App.Settings.MultiInstanceLaunching = value;
}
public IReadOnlyDictionary<string, Theme> Themes { get; set; } = new Dictionary<string, Theme>() public IReadOnlyDictionary<string, Theme> Themes { get; set; } = new Dictionary<string, Theme>()
{ {
{ "System Default", Enums.Theme.Default }, { "System Default", Enums.Theme.Default },

View File

@ -23,6 +23,15 @@
</ui:CardControl.Header> </ui:CardControl.Header>
<ui:ToggleSwitch IsChecked="{Binding UpdateCheckingEnabled, Mode=TwoWay}" /> <ui:ToggleSwitch IsChecked="{Binding UpdateCheckingEnabled, Mode=TwoWay}" />
</ui:CardControl> </ui:CardControl>
<ui:CardControl Margin="0,8,0,0">
<ui:CardControl.Header>
<StackPanel Grid.Column="0">
<TextBlock FontSize="13" FontWeight="Medium" Text="Allow multi-game instance launching" />
<TextBlock FontSize="12" Text="Roblox will allow having more than one game instance open simultaneously." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
</StackPanel>
</ui:CardControl.Header>
<ui:ToggleSwitch IsChecked="{Binding MultiInstanceLaunchingEnabled, Mode=TwoWay}" />
</ui:CardControl>
<ui:CardControl Margin="0,8,0,0"> <ui:CardControl Margin="0,8,0,0">
<ui:CardControl.Header> <ui:CardControl.Header>
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">