Skip to content

Commit 7bdbd77

Browse files
committed
still a fork
adds pr: (bloxstraplabs#4032)
1 parent 1b32335 commit 7bdbd77

File tree

10 files changed

+215
-21
lines changed

10 files changed

+215
-21
lines changed

Bloxstrap/App.xaml

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
<converters:StringFormatConverter x:Key="StringFormatConverter" />
3838
<converters:RangeConverter x:Key="RangeConverter" />
3939
<converters:EnumNameConverter x:Key="EnumNameConverter" />
40+
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
41+
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter" />
4042
</ResourceDictionary>
4143
</Application.Resources>
4244
</Application>

Bloxstrap/Bootstrapper.cs

+21-19
Original file line numberDiff line numberDiff line change
@@ -426,30 +426,32 @@ private void StartRoblox()
426426
// launch custom integrations now
427427
foreach (var integration in App.Settings.Prop.CustomIntegrations)
428428
{
429-
App.Logger.WriteLine(LOG_IDENT, $"Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})");
429+
if (!integration.SpecifyGame) {
430+
App.Logger.WriteLine(LOG_IDENT, $"Launching custom integration '{integration.Name}' ({integration.Location} {integration.LaunchArgs} - autoclose is {integration.AutoClose})");
430431

431-
int pid = 0;
432+
int pid = 0;
432433

433-
try
434-
{
435-
var process = Process.Start(new ProcessStartInfo
434+
try
436435
{
437-
FileName = integration.Location,
438-
Arguments = integration.LaunchArgs.Replace("\r\n", " "),
439-
WorkingDirectory = Path.GetDirectoryName(integration.Location),
440-
UseShellExecute = true
441-
})!;
436+
var process = Process.Start(new ProcessStartInfo
437+
{
438+
FileName = integration.Location,
439+
Arguments = integration.LaunchArgs.Replace("\r\n", " "),
440+
WorkingDirectory = Path.GetDirectoryName(integration.Location),
441+
UseShellExecute = true
442+
})!;
442443

443-
pid = process.Id;
444-
}
445-
catch (Exception ex)
446-
{
447-
App.Logger.WriteLine(LOG_IDENT, $"Failed to launch integration '{integration.Name}'!");
448-
App.Logger.WriteLine(LOG_IDENT, ex.Message);
449-
}
444+
pid = process.Id;
445+
}
446+
catch (Exception ex)
447+
{
448+
App.Logger.WriteLine(LOG_IDENT, $"Failed to launch integration '{integration.Name}'!");
449+
App.Logger.WriteLine(LOG_IDENT, ex.Message);
450+
}
450451

451-
if (integration.AutoClose && pid != 0)
452-
autoclosePids.Add(pid);
452+
if (integration.AutoClose && pid != 0)
453+
autoclosePids.Add(pid);
454+
}
453455
}
454456

455457
if (App.Settings.Prop.EnableActivityTracking || App.LaunchSettings.TestModeFlag.Active || autoclosePids.Any())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
namespace Bloxstrap.Integrations
2+
{
3+
public class IntegrationWatcher : IDisposable
4+
{
5+
private readonly ActivityWatcher _activityWatcher;
6+
private readonly Dictionary<int, CustomIntegration> _activeIntegrations = new();
7+
8+
public IntegrationWatcher(ActivityWatcher activityWatcher)
9+
{
10+
_activityWatcher = activityWatcher;
11+
12+
_activityWatcher.OnGameJoin += OnGameJoin;
13+
_activityWatcher.OnGameLeave += OnGameLeave;
14+
}
15+
16+
private void OnGameJoin(object? sender, EventArgs e)
17+
{
18+
if (!_activityWatcher.InGame)
19+
return;
20+
21+
long currentGameId = _activityWatcher.Data.PlaceId;
22+
23+
foreach (var integration in App.Settings.Prop.CustomIntegrations)
24+
{
25+
if (!integration.SpecifyGame || integration.GameID != currentGameId.ToString())
26+
continue;
27+
28+
LaunchIntegration(integration);
29+
}
30+
}
31+
32+
private void OnGameLeave(object? sender, EventArgs e)
33+
{
34+
foreach (var pid in _activeIntegrations.Keys.ToList())
35+
{
36+
var integration = _activeIntegrations[pid];
37+
if (integration.AutoCloseOnGame)
38+
{
39+
TerminateProcess(pid);
40+
_activeIntegrations.Remove(pid);
41+
}
42+
}
43+
}
44+
45+
private void LaunchIntegration(CustomIntegration integration)
46+
{
47+
const string LOG_IDENT = "IntegrationWatcher::LaunchIntegration";
48+
49+
try
50+
{
51+
var process = Process.Start(new ProcessStartInfo
52+
{
53+
FileName = integration.Location,
54+
Arguments = integration.LaunchArgs.Replace("\r\n", " "),
55+
WorkingDirectory = Path.GetDirectoryName(integration.Location),
56+
UseShellExecute = true
57+
});
58+
59+
if (process != null)
60+
{
61+
App.Logger.WriteLine(LOG_IDENT, $"Integration '{integration.Name}' launched for game ID '{integration.GameID}' (PID {process.Id}).");
62+
_activeIntegrations[process.Id] = integration;
63+
}
64+
}
65+
catch (Exception ex)
66+
{
67+
App.Logger.WriteLine(LOG_IDENT, $"Failed to launch integration '{integration.Name}': {ex.Message}");
68+
}
69+
}
70+
71+
private void TerminateProcess(int pid)
72+
{
73+
const string LOG_IDENT = "IntegrationWatcher::TerminateProcess";
74+
75+
try
76+
{
77+
var process = Process.GetProcessById(pid);
78+
process.Kill();
79+
80+
App.Logger.WriteLine(LOG_IDENT, $"Terminated integration process (PID {pid}).");
81+
}
82+
catch (Exception)
83+
{
84+
App.Logger.WriteLine(LOG_IDENT, $"Failed to terminate process (PID {pid}), likely already exited.");
85+
}
86+
}
87+
88+
public void Dispose()
89+
{
90+
foreach (var pid in _activeIntegrations.Keys)
91+
{
92+
TerminateProcess(pid);
93+
}
94+
95+
_activeIntegrations.Clear();
96+
97+
GC.SuppressFinalize(this);
98+
}
99+
}
100+
}

Bloxstrap/Models/CustomIntegration.cs

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ public class CustomIntegration
55
public string Name { get; set; } = "";
66
public string Location { get; set; } = "";
77
public string LaunchArgs { get; set; } = "";
8+
public bool SpecifyGame { get; set; } = false;
9+
public string GameID { get; set; } = "";
10+
public bool AutoCloseOnGame { get; set; } = true;
811
public bool AutoClose { get; set; } = true;
912
}
1013
}

Bloxstrap/Resources/Strings.Designer.cs

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Bloxstrap/Resources/Strings.resx

+9
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,15 @@ Selecting 'No' will ignore this warning and continue installation.</value>
689689
<data name="Menu.Integrations.Custom.AppLocation" xml:space="preserve">
690690
<value>Application Location</value>
691691
</data>
692+
<data name="Menu.Integrations.Custom.SpecifyGame" xml:space="preserve">
693+
<value>Run on a specific game</value>
694+
</data>
695+
<data name="Menu.Integrations.Custom.GameID" xml:space="preserve">
696+
<value>Game ID</value>
697+
</data>
698+
<data name="Menu.Integrations.Custom.AutoCloseOnGame" xml:space="preserve">
699+
<value>Auto close when the game closes</value>
700+
</data>
692701
<data name="Menu.Integrations.Custom.AutoClose" xml:space="preserve">
693702
<value>Auto close when Roblox closes</value>
694703
</data>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Windows;
2+
using System.Windows.Data;
3+
4+
namespace Bloxstrap.UI.Converters
5+
{
6+
public class BooleanToVisibilityConverter : IValueConverter
7+
{
8+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
9+
{
10+
if (value is bool boolValue)
11+
return boolValue ? Visibility.Visible : Visibility.Collapsed;
12+
13+
return Visibility.Collapsed;
14+
}
15+
16+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
17+
{
18+
throw new NotImplementedException();
19+
}
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Windows;
2+
using System.Windows.Data;
3+
4+
namespace Bloxstrap.UI.Converters
5+
{
6+
public class InverseBooleanToVisibilityConverter : IValueConverter
7+
{
8+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
9+
{
10+
if (value is bool boolValue)
11+
return boolValue ? Visibility.Collapsed : Visibility.Visible;
12+
13+
return Visibility.Visible;
14+
}
15+
16+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
17+
{
18+
throw new NotImplementedException();
19+
}
20+
}
21+
}

Bloxstrap/UI/Elements/Settings/Pages/IntegrationsPage.xaml

+6-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868

6969
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_Custom_Title}" FontSize="20" FontWeight="Medium" Margin="0,16,0,0" />
7070
<TextBlock Text="{x:Static resources:Strings.Menu_Integrations_Custom_Description}" TextWrapping="Wrap" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
71-
<Grid Margin="0,8,0,0">
71+
<Grid Margin="0,8,0,0", MinHeight="325">
7272
<Grid.RowDefinitions>
7373
<RowDefinition Height="*" />
7474
<RowDefinition Height="Auto" />
@@ -109,7 +109,11 @@
109109
</Grid>
110110
<TextBlock Margin="0,8,0,0" Text="{x:Static resources:Strings.Menu_Integrations_Custom_LaunchArgs}" Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
111111
<ui:TextBox Margin="0,4,0,0" PlaceholderText="{Binding Source='/k echo {0}', Converter={StaticResource StringFormatConverter}, ConverterParameter={x:Static resources:Strings.Menu_Integrations_Custom_LaunchArgs_Placeholder}}" Text="{Binding SelectedCustomIntegration.LaunchArgs}" TextWrapping="Wrap" AcceptsReturn="True" AcceptsTab="True" />
112-
<CheckBox Margin="0,8,0,0" Content="{x:Static resources:Strings.Menu_Integrations_Custom_AutoClose}" IsChecked="{Binding SelectedCustomIntegration.AutoClose}" />
112+
<CheckBox Margin="0,8,0,0" Content="{x:Static resources:Strings.Menu_Integrations_Custom_SpecifyGame}" IsChecked="{Binding SelectedCustomIntegration.SpecifyGame, UpdateSourceTrigger=PropertyChanged}" />
113+
<TextBlock Margin="0,8,0,0" Text="{x:Static resources:Strings.Menu_Integrations_Custom_GameID}" Foreground="{DynamicResource TextFillColorSecondaryBrush}" Visibility="{Binding SelectedCustomIntegration.SpecifyGame, Converter={StaticResource BooleanToVisibilityConverter}}" />
114+
<ui:TextBox Margin="0,4,0,0" PlaceholderText="1818" Text="{Binding SelectedCustomIntegration.GameID}" Visibility="{Binding SelectedCustomIntegration.SpecifyGame, Converter={StaticResource BooleanToVisibilityConverter}}" />
115+
<CheckBox Margin="0,8,0,0" Content="{x:Static resources:Strings.Menu_Integrations_Custom_AutoCloseOnGame}" IsChecked="{Binding SelectedCustomIntegration.AutoCloseOnGame, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding SelectedCustomIntegration.SpecifyGame, Converter={StaticResource BooleanToVisibilityConverter}}" />
116+
<CheckBox Margin="0,8,0,0" Content="{x:Static resources:Strings.Menu_Integrations_Custom_AutoClose}" IsChecked="{Binding SelectedCustomIntegration.AutoClose, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding SelectedCustomIntegration.SpecifyGame, Converter={StaticResource InverseBooleanToVisibilityConverter}}" />
113117
</StackPanel>
114118
<TextBlock Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Text="{x:Static resources:Strings.Menu_Integrations_Custom_NoneSelected}" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center">
115119
<TextBlock.Style>

Bloxstrap/Watcher.cs

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public class Watcher : IDisposable
1616

1717
public readonly DiscordRichPresence? RichPresence;
1818

19+
public readonly IntegrationWatcher? IntegrationWatcher;
20+
1921
public Mutex? _mutexd = null;
2022

2123
public Watcher(Mutex? mutexd = null)
@@ -67,6 +69,8 @@ public Watcher(Mutex? mutexd = null)
6769

6870
if (App.Settings.Prop.UseDiscordRichPresence)
6971
RichPresence = new(ActivityWatcher);
72+
73+
IntegrationWatcher = new IntegrationWatcher(ActivityWatcher);
7074
}
7175

7276
_notifyIcon = new(this);
@@ -128,6 +132,7 @@ public void Dispose()
128132
{
129133
App.Logger.WriteLine("Watcher::Dispose", "Disposing Watcher");
130134

135+
IntegrationWatcher?.Dispose();
131136
_notifyIcon?.Dispose();
132137
RichPresence?.Dispose();
133138

0 commit comments

Comments
 (0)