Skip to content

Commit 41ac305

Browse files
committed
release: Register the game's package on activation & remove framework checks.
1 parent 9e933c1 commit 41ac305

File tree

6 files changed

+79
-55
lines changed

6 files changed

+79
-55
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ internal Minecraft() { }
2323
protected abstract string Window { get; }
2424
protected abstract string Process { get; }
2525

26-
public static readonly string PackageFamilyName = "Microsoft.MinecraftUWP_8wekyb3d8bbwe";
27-
public static Minecraft Current => UsingGameDevelopmentKit ? s_gdk : throw new PlatformNotSupportedException();
26+
public static Minecraft Current { get; } = new MinecraftGDK();
27+
public static string PackageFamilyName { get; } = "Microsoft.MinecraftUWP_8wekyb3d8bbwe";
2828

29-
static readonly Minecraft s_gdk = new MinecraftGDK();
3029
internal static Package Package => PackageService.GetPackage(PackageFamilyName)!;
3130

3231
internal static string Version
@@ -53,6 +52,8 @@ internal static string Version
5352
public static bool IsInstalled => Package is { };
5453
public static bool IsPackaged => Package.SignatureKind is PackageSignatureKind.Store;
5554
public static bool IsGamingServicesInstalled => PackageService.GetPackage("Microsoft.GamingServices_8wekyb3d8bbwe") is { };
55+
56+
[Obsolete("", true)]
5657
public static bool UsingGameDevelopmentKit => Package.GetAppListEntries()[0].AppUserModelId.Equals("Microsoft.MinecraftUWP_8wekyb3d8bbwe!Game", OrdinalIgnoreCase);
5758

5859
internal static uint? GetProcessId(string target)

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

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Management.Automation;
55
using System.Management.Automation.Runspaces;
6+
using Flarial.Launcher.Runtime.Services;
67
using Windows.ApplicationModel;
78
using Windows.Win32.Foundation;
89
using static System.Environment;
@@ -35,14 +36,20 @@ static MinecraftGDK()
3536

3637
protected override uint? Activate()
3738
{
38-
var path = Path.Combine(Package.InstalledPath, Process);
39-
40-
if (!File.Exists(path))
41-
throw new FileNotFoundException(null, path);
42-
4339
if (GetProcessId() is { } processId)
4440
return processId;
4541

42+
/*
43+
- Register the package to ensure it is installed.
44+
- This allows the launcher to discover the game's executable.
45+
*/
46+
47+
if (!PackageService.RegisterPackage(Package))
48+
throw new Win32Exception((int)ERROR_INSTALL_REGISTRATION_FAILURE);
49+
50+
var path = Path.Combine(Package.InstalledPath, Process);
51+
if (!File.Exists(path)) throw new FileNotFoundException(null, path);
52+
4653
/*
4754
- We use PowerShell to directly start the game.
4855
- This simplifies the activation contract.
@@ -77,11 +84,8 @@ static MinecraftGDK()
7784
return target.ProcessId;
7885
}
7986

80-
if (Activate() is not { } processId)
81-
return null;
82-
83-
if (Open(PROCESS_SYNCHRONIZE, processId) is not { } process)
84-
return null;
87+
if (Activate() is not { } processId) return null;
88+
if (Open(PROCESS_SYNCHRONIZE, processId) is not { } process) return null;
8589

8690
using (process)
8791
{
@@ -95,14 +99,9 @@ static MinecraftGDK()
9599
{
96100
while (process.Wait(1))
97101
{
98-
if (GetWindow() is not { } instance)
99-
continue;
100-
101-
if (instance.ProcessId != processId)
102-
continue;
103-
104-
if (instance.IsVisible)
105-
return processId;
102+
if (GetWindow() is not { } instance) continue;
103+
if (instance.ProcessId != processId) continue;
104+
if (instance.IsVisible) return processId;
106105
}
107106
return null;
108107
}
Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Linq;
34
using Windows.ApplicationModel;
45
using Windows.Management.Deployment;
@@ -10,14 +11,21 @@ namespace Flarial.Launcher.Runtime.Services;
1011

1112
unsafe static class PackageService
1213
{
13-
static readonly PackageManager s_packageManager = new();
14+
static readonly PackageManager s_pm = new();
1415

15-
internal static Package? GetPackage(string packageFamilyName) => s_packageManager.FindPackagesForUser(string.Empty, packageFamilyName).FirstOrDefault();
16+
static readonly RegisterPackageOptions s_rpo = new()
17+
{
18+
DeveloperMode = true,
19+
ForceAppShutdown = true,
20+
ForceUpdateFromAnyVersion = true
21+
};
22+
23+
internal static Package? GetPackage(string packageFamilyName) => s_pm.FindPackagesForUser(string.Empty, packageFamilyName).FirstOrDefault();
1624

17-
internal static void AddPackage(Uri uri, Action<int> callback)
25+
internal static bool AddPackage(Uri uri, Action<int> callback)
1826
{
1927
var handle = CreateEvent(null, true, false, null);
20-
var info = s_packageManager.AddPackageAsync(uri, null, ForceApplicationShutdown | ForceUpdateFromAnyVersion);
28+
var info = s_pm.AddPackageAsync(uri, null, ForceApplicationShutdown | ForceUpdateFromAnyVersion);
2129

2230
try
2331
{
@@ -26,7 +34,45 @@ internal static void AddPackage(Uri uri, Action<int> callback)
2634

2735
WaitForSingleObject(handle, INFINITE);
2836
if (info.Status is Error) throw info.ErrorCode;
37+
38+
var result = info.GetResults();
39+
if (result.ExtendedErrorCode is { } @_) throw @_;
40+
41+
return result.IsRegistered;
42+
}
43+
finally
44+
{
45+
CloseHandle(handle);
46+
info.Close();
47+
}
48+
}
49+
50+
internal static bool RegisterPackage(Package package)
51+
{
52+
var name = package.Id.FullName;
53+
54+
var options = ForceApplicationShutdown;
55+
if (package.IsDevelopmentMode) options |= DevelopmentMode;
56+
57+
var handle = CreateEvent(null, true, false, null);
58+
var info = s_pm.RegisterPackageByFullNameAsync(name, null, options);
59+
60+
try
61+
{
62+
info.Completed += (_, _) => SetEvent(handle);
63+
64+
WaitForSingleObject(handle, INFINITE);
65+
if (info.Status is Error) throw info.ErrorCode;
66+
67+
var result = info.GetResults();
68+
if (result.ExtendedErrorCode is { } @_) throw @_;
69+
70+
return result.IsRegistered;
71+
}
72+
finally
73+
{
74+
CloseHandle(handle);
75+
info.Close();
2976
}
30-
finally { CloseHandle(handle); info.Close(); }
3177
}
3278
}

src/Flarial.Launcher/Interface/Dialogs/UWPDeprecatedDialog.cs

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

src/Flarial.Launcher/Interface/MainDialog.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ internal async Task<ContentDialogResult> PromptAsync()
4242
internal static NotInstalledDialog NotInstalled => field ??= new();
4343
internal static LaunchFailureDialog LaunchFailure => field ??= new();
4444
internal static SelectVersionDialog SelectVersion => field ??= new();
45-
internal static UWPDeprecatedDialog UWPDeprecated => field ??= new();
4645
internal static InstallVersionDialog InstallVersion => field ??= new();
4746
internal static UnsignedInstallDialog UnsignedInstall => field ??= new();
4847
internal static InvalidCustomDllDialog InvalidCustomDll => field ??= new();

src/Flarial.Launcher/Pages/HomePage.cs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -131,24 +131,16 @@ async void OnButtonClick(object sender, RoutedEventArgs args)
131131
return;
132132
}
133133

134-
if (Minecraft.UsingGameDevelopmentKit)
134+
if (!Minecraft.IsGamingServicesInstalled)
135135
{
136-
if (!Minecraft.IsGamingServicesInstalled)
137-
{
138-
await MainDialog.GamingServicesMissing.ShowAsync();
139-
return;
140-
}
141-
142-
if (!Minecraft.IsPackaged)
143-
{
144-
if (!await MainDialog.UnsignedInstall.ShowAsync())
145-
return;
146-
}
136+
await MainDialog.GamingServicesMissing.ShowAsync();
137+
return;
147138
}
148-
else
139+
140+
if (!Minecraft.IsPackaged)
149141
{
150-
await MainDialog.UWPDeprecated.ShowAsync();
151-
return;
142+
if (!await MainDialog.UnsignedInstall.ShowAsync())
143+
return;
152144
}
153145

154146
if (!custom && !registry.IsSupported)

0 commit comments

Comments
 (0)