Skip to content

Commit e356fa5

Browse files
committed
Improve client injection speed & cleanup settings page.
1 parent 5bad46a commit e356fa5

File tree

11 files changed

+109
-235
lines changed

11 files changed

+109
-235
lines changed

src/Flarial.Launcher.Runtime/Client/FlarialClient.cs

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,58 +6,45 @@
66
using Flarial.Launcher.Runtime.Game;
77
using Flarial.Launcher.Runtime.Modding;
88
using Flarial.Launcher.Runtime.Services;
9-
using Flarial.Launcher.Runtime.System;
109
using static System.StringComparison;
1110

1211
namespace Flarial.Launcher.Runtime.Client;
1312

1413
sealed class FlarialClientRelease : FlarialClient
1514
{
16-
protected override string Build => nameof(Release);
17-
protected override string FileName => $"Flarial.Client.{nameof(Release)}.dll";
18-
protected override string Identifer => "34F45015-6EB6-4213-ABEF-F2967818E628";
15+
protected override string Build => "Release";
16+
protected override string WindowClass => "Flarial Client";
17+
protected override string FileName => "Flarial.Client.Release.dll";
1918
protected override string DownloadUri => "https://cdn.flarial.xyz/dll/latest.dll";
2019
}
2120

2221
public abstract class FlarialClient
2322
{
2423
internal FlarialClient() { }
24+
25+
public static FlarialClient Current { get; } = new FlarialClientRelease();
2526
static readonly JsonService<Dictionary<string, string>> s_json = JsonService<Dictionary<string, string>>.GetJson();
2627

2728
protected abstract string Build { get; }
2829
protected abstract string FileName { get; }
29-
protected abstract string Identifer { get; }
3030
protected abstract string DownloadUri { get; }
31+
protected abstract string WindowClass { get; }
3132

32-
public static readonly FlarialClient Release = new FlarialClientRelease();
33-
34-
static FlarialClient? Current
35-
{
36-
get
37-
{
38-
if (!Minecraft.Current.IsRunning) return null;
39-
using NativeMutex release = new(Release.Identifer);
40-
return release.Exists ? Release : null;
41-
}
42-
}
43-
44-
public bool Launch(bool? initialized)
33+
public bool Launch()
4534
{
46-
if (Current is { } client)
35+
if (Minecraft.GetWindow(WindowClass) is { } client)
4736
{
48-
if (!ReferenceEquals(this, client)) return false;
49-
return Minecraft.Current.Launch(null) is { };
50-
}
51-
52-
if (Injector.Launch(initialized, new(FileName)) is not { } processId)
37+
if (Minecraft.Current.GetWindow(client._processId) is { } minecraft)
38+
{
39+
minecraft.SwitchWindow();
40+
return true;
41+
}
5342
return false;
54-
55-
using NativeMutex mutex = new(Identifer);
56-
return mutex.Duplicate(processId);
43+
}
44+
return Injector.Launch(null, new(FileName)) is { };
5745
}
5846

5947
static readonly object _lock = new();
60-
6148
static readonly HashAlgorithm _algorithm = SHA256.Create();
6249

6350
const string HashesUrl = "https://cdn.flarial.xyz/dll_hashes.json";

src/Flarial.Launcher.Runtime/Game/Minecraft.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Runtime.InteropServices;
23
using Flarial.Launcher.Runtime.Services;
34
using Flarial.Launcher.Runtime.System;
@@ -25,7 +26,9 @@ internal Minecraft() { }
2526
public static Minecraft Current { get; } = new MinecraftGDK();
2627
public static string PackageFamilyName { get; } = "Microsoft.MinecraftUWP_8wekyb3d8bbwe";
2728

29+
[Obsolete("", true)]
2830
internal bool IsRunning => GetWindow() is { };
31+
2932
internal static Package Package => PackageService.GetPackage(PackageFamilyName)!;
3033
internal static string Version { get { var _ = Package.Id.Version; return $"{_.Major}.{_.Minor}.{_.Build / 100}"; } }
3134

@@ -38,7 +41,7 @@ internal Minecraft() { }
3841
*/
3942

4043
private protected uint? GetProcessId() => GetProcessId(ProcessName);
41-
private protected NativeWindow? GetWindow([Optional] uint? processId) => GetWindow(WindowClass, processId);
44+
internal NativeWindow? GetWindow([Optional] uint? processId) => GetWindow(WindowClass, processId);
4245

4346
public static bool IsInstalled => Package is { };
4447
public static bool IsPackaged => Package.SignatureKind is PackageSignatureKind.Store;
@@ -75,7 +78,7 @@ internal Minecraft() { }
7578
}
7679
}
7780

78-
static NativeWindow? GetWindow(string windowClass, [Optional] uint? processId)
81+
internal static NativeWindow? GetWindow(string windowClass, [Optional] uint? processId)
7982
{
8083
fixed (char* wc = windowClass)
8184
fixed (char* pfn = PackageFamilyName)
@@ -86,10 +89,10 @@ internal Minecraft() { }
8689

8790
while ((window = FindWindowEx(HWND.Null, window, wc, null)) != HWND.Null)
8891
{
89-
if (processId is { } && processId != window.ProcessId)
92+
if (processId is { } && processId != window._processId)
9093
continue;
9194

92-
if (Open(PROCESS_QUERY_LIMITED_INFORMATION, window.ProcessId) is not { } process)
95+
if (Open(PROCESS_QUERY_LIMITED_INFORMATION, window._processId) is not { } process)
9396
continue;
9497

9598
using (process)

src/Flarial.Launcher.Runtime/Game/MinecraftGDK.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Management.Automation.Runspaces;
66
using System.Threading;
77
using Flarial.Launcher.Runtime.Services;
8+
using Flarial.Launcher.Runtime.System;
89
using Windows.ApplicationModel;
910
using Windows.Win32.Foundation;
1011
using static System.Environment;
@@ -69,10 +70,10 @@ static MinecraftGDK()
6970
if (!IsGamingServicesInstalled)
7071
throw new Win32Exception((int)ERROR_INSTALL_PREREQUISITE_FAILED);
7172

72-
if (GetWindow() is { } @_ && _.IsVisible)
73+
if (GetWindow() is { } foundWindow && foundWindow.IsVisible)
7374
{
74-
_.Switch();
75-
return _.ProcessId;
75+
foundWindow.SwitchWindow();
76+
return foundWindow._processId;
7677
}
7778

7879
if (Activate() is not { } processId)
@@ -91,14 +92,16 @@ static MinecraftGDK()
9192

9293
if (initialized is null || !IsPackaged)
9394
{
95+
NativeWindow? processWindow = null;
96+
9497
while (process.Wait(1))
95-
{
96-
if (GetWindow(processId) is not { } window)
97-
continue;
98+
if ((processWindow = GetWindow()) is { })
99+
break;
98100

99-
if (window.IsVisible)
101+
while (process.Wait(1))
102+
if (processWindow?.IsVisible ?? false)
100103
return processId;
101-
}
104+
102105
return null;
103106
}
104107

src/Flarial.Launcher.Runtime/System/NativeMutex.cs

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/Flarial.Launcher.Runtime/System/NativeWindow.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1+
using System;
12
using System.Runtime.InteropServices;
23
using Windows.Win32.Foundation;
34
using static Windows.Win32.PInvoke;
45

56
namespace Flarial.Launcher.Runtime.System;
67

7-
unsafe readonly struct NativeWindow(HWND handle)
8+
unsafe readonly struct NativeWindow
89
{
9-
readonly HWND _handle = handle;
10+
readonly HWND _handle;
11+
internal readonly uint _processId;
1012

11-
internal void Switch() => SwitchToThisWindow(_handle, true);
13+
internal NativeWindow(HWND handle)
14+
{
15+
uint processId = 0;
16+
GetWindowThreadProcessId(handle, &processId);
17+
18+
_handle = handle;
19+
_processId = processId;
20+
}
1221

1322
internal bool IsVisible => IsWindowVisible(_handle);
14-
internal uint ProcessId { get { uint _; GetWindowThreadProcessId(_handle, &_); return _; } }
23+
internal void SwitchWindow() => SwitchToThisWindow(_handle, true);
1524

1625
public static implicit operator NativeWindow(in HWND hwnd) => new(hwnd);
1726
public static implicit operator HWND(in NativeWindow window) => window._handle;

src/Flarial.Launcher/Controls/ContentItem.cs

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/Flarial.Launcher/Controls/DllSelectionBox.cs

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,73 +7,49 @@ namespace Flarial.Launcher.Controls;
77

88
sealed class DllSelectionBox : Grid
99
{
10+
readonly CustomDllButton _button;
1011
readonly ApplicationSettings _settings;
1112

12-
readonly ListBox _listBox = new()
13+
readonly ToggleSwitch _toggleSwitch = new()
1314
{
15+
Header = "Should the launcher use a custom DLL?",
1416
VerticalAlignment = VerticalAlignment.Stretch,
15-
HorizontalAlignment = HorizontalAlignment.Stretch
17+
HorizontalAlignment = HorizontalAlignment.Stretch,
18+
OnContent = "Yes, use a custom DLL.",
19+
OffContent = "No, use the client's DLL."
1620
};
1721

18-
readonly CustomDllButton _button;
19-
20-
void OnListBoxSelectionChanged(object sender, RoutedEventArgs args)
22+
void OnToggleSwitchToggled(object sender, RoutedEventArgs args)
2123
{
22-
var listBox = (ListBox)sender;
24+
var value = ((ToggleSwitch)sender).IsOn;
2325

24-
var item = (ContentItem<DllSelection>)listBox.SelectedItem;
25-
_settings.DllSelection = item.Value;
26+
_button._button.IsEnabled = value;
27+
_button._textBox.IsEnabled = value;
2628

27-
var enabled = item.Value is DllSelection.Custom;
28-
_button._button.IsEnabled = enabled;
29-
_button._textBox.IsEnabled = enabled;
29+
_settings.UseCustomDll = value;
3030
}
3131

3232
internal DllSelectionBox(ApplicationSettings settings)
3333
{
3434
_settings = settings;
35-
_button = new(_settings);
35+
_button = new(settings);
36+
37+
RowSpacing = 12;
38+
ColumnSpacing = 12;
3639

3740
RowDefinitions.Add(new());
3841
RowDefinitions.Add(new() { Height = GridLength.Auto });
3942

40-
SetRow(_listBox, 0);
41-
SetColumn(_listBox, 0);
43+
SetRow(_toggleSwitch, 0);
44+
SetColumn(_toggleSwitch, 0);
4245

4346
SetRow(_button, 1);
4447
SetColumn(_button, 0);
4548

46-
Children.Add(_listBox);
49+
Children.Add(_toggleSwitch);
4750
Children.Add(_button);
4851

49-
_listBox.Items.Add(new ClientDll());
50-
_listBox.Items.Add(new CustomDll());
51-
52-
_listBox.SelectionChanged += OnListBoxSelectionChanged;
53-
54-
_listBox.SetValue(VirtualizingStackPanel.IsVirtualizingProperty, true);
55-
VirtualizingStackPanel.SetVirtualizationMode(_listBox, VirtualizationMode.Recycling);
56-
57-
_listBox.SelectedIndex = (int)_settings.DllSelection;
58-
}
59-
60-
[Obsolete("", true)]
61-
abstract class DllItem
62-
{
63-
protected abstract string String { get; }
64-
public override string ToString() => String;
65-
internal abstract DllSelection Value { get; }
66-
}
67-
68-
sealed class ClientDll : ContentItem<DllSelection>
69-
{
70-
protected override string String => "Use the client's DLL with the game.";
71-
internal override DllSelection Value => DllSelection.Client;
72-
}
73-
74-
sealed class CustomDll : ContentItem<DllSelection>
75-
{
76-
protected override string String => "Use a specified custom DLL with the game.";
77-
internal override DllSelection Value => DllSelection.Custom;
52+
_toggleSwitch.Toggled += OnToggleSwitchToggled;
53+
_toggleSwitch.IsOn = _settings.UseCustomDll;
7854
}
7955
}

0 commit comments

Comments
 (0)