From a90dd0fbe998822c2a90282ff1950e25fb2ad69f Mon Sep 17 00:00:00 2001 From: MCMrARM Date: Thu, 10 Feb 2022 15:50:28 +0100 Subject: [PATCH 1/5] Show preview builds on a separate tab --- MCLauncher/MainWindow.xaml | 7 ++++++ MCLauncher/MainWindow.xaml.cs | 47 ++++++++++++++++++++++++++--------- MCLauncher/VersionList.cs | 4 +-- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/MCLauncher/MainWindow.xaml b/MCLauncher/MainWindow.xaml index 6315beb..7469a30 100644 --- a/MCLauncher/MainWindow.xaml +++ b/MCLauncher/MainWindow.xaml @@ -15,6 +15,10 @@ x:Key="versionListViewBeta" IsLiveFilteringRequested="True" /> + + + + diff --git a/MCLauncher/MainWindow.xaml.cs b/MCLauncher/MainWindow.xaml.cs index 2a28d39..7ec9829 100644 --- a/MCLauncher/MainWindow.xaml.cs +++ b/MCLauncher/MainWindow.xaml.cs @@ -56,7 +56,7 @@ public MainWindow() { var versionListViewRelease = Resources["versionListViewRelease"] as CollectionViewSource; versionListViewRelease.Filter += new FilterEventHandler((object sender, FilterEventArgs e) => { var v = e.Item as Version; - e.Accepted = !v.IsImported && !v.IsBeta && (v.IsInstalled || v.IsStateChanging || !(ShowInstalledVersionsOnlyCheckbox.IsChecked ?? false)); + e.Accepted = v.VersionType == VersionType.Release && (v.IsInstalled || v.IsStateChanging || !(ShowInstalledVersionsOnlyCheckbox.IsChecked ?? false)); }); versionListViewRelease.Source = _versions; ReleaseVersionList.DataContext = versionListViewRelease; @@ -65,16 +65,25 @@ public MainWindow() { var versionListViewBeta = Resources["versionListViewBeta"] as CollectionViewSource; versionListViewBeta.Filter += new FilterEventHandler((object sender, FilterEventArgs e) => { var v = e.Item as Version; - e.Accepted = !v.IsImported && v.IsBeta && (v.IsInstalled || v.IsStateChanging || !(ShowInstalledVersionsOnlyCheckbox.IsChecked ?? false)); + e.Accepted = v.VersionType == VersionType.Beta && (v.IsInstalled || v.IsStateChanging || !(ShowInstalledVersionsOnlyCheckbox.IsChecked ?? false)); }); versionListViewBeta.Source = _versions; BetaVersionList.DataContext = versionListViewBeta; _versionListViews.Add(versionListViewBeta); + var versionListViewPreview = Resources["versionListViewPreview"] as CollectionViewSource; + versionListViewPreview.Filter += new FilterEventHandler((object sender, FilterEventArgs e) => { + var v = e.Item as Version; + e.Accepted = v.VersionType == VersionType.Preview && (v.IsInstalled || v.IsStateChanging || !(ShowInstalledVersionsOnlyCheckbox.IsChecked ?? false)); + }); + versionListViewPreview.Source = _versions; + PreviewVersionList.DataContext = versionListViewPreview; + _versionListViews.Add(versionListViewPreview); + var versionListViewImported = Resources["versionListViewImported"] as CollectionViewSource; versionListViewImported.Filter += new FilterEventHandler((object sender, FilterEventArgs e) => { var v = e.Item as Version; - e.Accepted = v.IsImported; + e.Accepted = v.VersionType == VersionType.Imported; }); versionListViewImported.Source = _versions; @@ -327,7 +336,7 @@ private void InvokeDownload(Version v) { Task.Run(async () => { string dlPath = "Minecraft-" + v.Name + ".Appx"; VersionDownloader downloader = _anonVersionDownloader; - if (v.IsBeta) { + if (v.VersionType == VersionType.Beta) { downloader = _userVersionDownloader; if (Interlocked.CompareExchange(ref _userVersionDownloaderLoginTaskStarted, 1, 0) == 0) { _userVersionDownloaderLoginTask.Start(); @@ -363,7 +372,7 @@ await downloader.Download(v.UUID, "1", dlPath, (current, total) => { Debug.WriteLine("Download failed due to failure to fetch download URL"); MessageBox.Show( "Unable to fetch download URL for version." + - (v.IsBeta ? "\nFor beta versions, please make sure your account is subscribed to the Minecraft beta programme in the Xbox Insider Hub app." : "") + (v.VersionType == VersionType.Beta ? "\nFor beta versions, please make sure your account is subscribed to the Minecraft beta programme in the Xbox Insider Hub app." : "") ); v.StateChangeInfo = null; return; @@ -497,13 +506,21 @@ public interface ICommonVersionCommands { } + public enum VersionType : int + { + Release = 0, + Beta = 1, + Preview = 2, + Imported = 100 + } + public class Version : NotifyPropertyChangedBase { public static readonly string UNKNOWN_UUID = "UNKNOWN"; - public Version(string uuid, string name, bool isBeta, bool isNew, ICommonVersionCommands commands) { + public Version(string uuid, string name, VersionType versionType, bool isNew, ICommonVersionCommands commands) { this.UUID = uuid; this.Name = name; - this.IsBeta = isBeta; + this.VersionType = versionType; this.IsNew = isNew; this.DownloadCommand = commands.DownloadCommand; this.LaunchCommand = commands.LaunchCommand; @@ -513,17 +530,16 @@ public Version(string uuid, string name, bool isBeta, bool isNew, ICommonVersion public Version(string name, string directory, ICommonVersionCommands commands) { this.UUID = UNKNOWN_UUID; this.Name = name; - this.IsBeta = false; + this.VersionType = VersionType.Imported; this.DownloadCommand = commands.DownloadCommand; this.LaunchCommand = commands.LaunchCommand; this.RemoveCommand = commands.RemoveCommand; this.GameDirectory = directory; - this.IsImported = true; } public string UUID { get; set; } public string Name { get; set; } - public bool IsBeta { get; set; } + public VersionType VersionType { get; set; } public bool IsNew { get { return _isNew; } set { @@ -531,7 +547,9 @@ public bool IsNew { OnPropertyChanged("IsNew"); } } - public bool IsImported { get; private set; } + public bool IsImported { + get => VersionType == VersionType.Imported; + } public string GameDirectory { get; set; } @@ -539,7 +557,12 @@ public bool IsNew { public string DisplayName { get { - return Name + (IsBeta ? " (beta)" : "") + (IsNew ? " (NEW!)" : ""); + string typeTag = ""; + if (VersionType == VersionType.Beta) + typeTag = "(beta)"; + else if (VersionType == VersionType.Preview) + typeTag = "(preview)"; + return Name + (typeTag.Length > 0 ? " " + typeTag : "") + (IsNew ? " (NEW!)" : ""); } } public string DisplayInstallStatus { diff --git a/MCLauncher/VersionList.cs b/MCLauncher/VersionList.cs index be67568..c7debd1 100644 --- a/MCLauncher/VersionList.cs +++ b/MCLauncher/VersionList.cs @@ -46,10 +46,10 @@ private void versionListOnCollectionChanged(object sender, NotifyCollectionChang private void ParseList(JArray data, bool isCache) { Clear(); - // ([name, uuid, isBeta])[] + // ([name, uuid, versionType])[] foreach (JArray o in data.AsEnumerable().Reverse()) { bool isNew = dbVersions.Add(o[0].Value()) && !isCache; - Add(new WPFDataTypes.Version(o[1].Value(), o[0].Value(), o[2].Value() == 1, isNew, _commands)); + Add(new WPFDataTypes.Version(o[1].Value(), o[0].Value(), (WPFDataTypes.VersionType) o[2].Value(), isNew, _commands)); } } From a15afd765d34a64b29de95b3b73b704a33e95cd7 Mon Sep 17 00:00:00 2001 From: MCMrARM Date: Thu, 10 Feb 2022 16:01:06 +0100 Subject: [PATCH 2/5] Support for separate package families --- MCLauncher/MainWindow.xaml.cs | 45 ++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/MCLauncher/MainWindow.xaml.cs b/MCLauncher/MainWindow.xaml.cs index 7ec9829..e7c2a99 100644 --- a/MCLauncher/MainWindow.xaml.cs +++ b/MCLauncher/MainWindow.xaml.cs @@ -24,7 +24,6 @@ namespace MCLauncher { /// public partial class MainWindow : Window, ICommonVersionCommands { - private static readonly string MINECRAFT_PACKAGE_FAMILY = "Microsoft.MinecraftUWP_8wekyb3d8bbwe"; private static readonly string PREFS_PATH = @"preferences.json"; private static readonly string IMPORTED_VERSIONS_PATH = @"imported_versions"; private static readonly string VERSIONS_API = "https://mrarm.io/r/w10-vdb"; @@ -188,7 +187,7 @@ private void InvokeLaunch(Version v) { v.StateChangeInfo = new VersionStateChangeInfo(VersionState.Registering); string gameDir = Path.GetFullPath(v.GameDirectory); try { - await ReRegisterPackage(gameDir); + await ReRegisterPackage(v.GamePackageFamily, gameDir); } catch (Exception e) { Debug.WriteLine("App re-register failed:\n" + e.ToString()); MessageBox.Show("App re-register failed:\n" + e.ToString()); @@ -198,7 +197,7 @@ private void InvokeLaunch(Version v) { } v.StateChangeInfo = new VersionStateChangeInfo(VersionState.Launching); try { - var pkg = await AppDiagnosticInfo.RequestInfoForPackageAsync(MINECRAFT_PACKAGE_FAMILY); + var pkg = await AppDiagnosticInfo.RequestInfoForPackageAsync(v.GamePackageFamily); if (pkg.Count > 0) await pkg[0].LaunchAsync(); Debug.WriteLine("App launch finished!"); @@ -237,8 +236,8 @@ private string GetBackupMinecraftDataDir() { return tmpDir; } - private void BackupMinecraftDataForRemoval() { - var data = ApplicationDataManager.CreateForPackageFamily(MINECRAFT_PACKAGE_FAMILY); + private void BackupMinecraftDataForRemoval(string packageFamily) { + var data = ApplicationDataManager.CreateForPackageFamily(packageFamily); string tmpDir = GetBackupMinecraftDataDir(); if (Directory.Exists(tmpDir)) { Debug.WriteLine("BackupMinecraftDataForRemoval error: " + tmpDir + " already exists"); @@ -271,20 +270,20 @@ private void RestoreMove(string from, string to) { } } - private void RestoreMinecraftDataFromReinstall() { + private void RestoreMinecraftDataFromReinstall(string packageFamily) { string tmpDir = GetBackupMinecraftDataDir(); if (!Directory.Exists(tmpDir)) return; - var data = ApplicationDataManager.CreateForPackageFamily(MINECRAFT_PACKAGE_FAMILY); + var data = ApplicationDataManager.CreateForPackageFamily(packageFamily); Debug.WriteLine("Moving backup Minecraft data to: " + data.LocalFolder.Path); RestoreMove(tmpDir, data.LocalFolder.Path); Directory.Delete(tmpDir, true); } - private async Task RemovePackage(Package pkg) { + private async Task RemovePackage(Package pkg, string packageFamily) { Debug.WriteLine("Removing package: " + pkg.Id.FullName); if (!pkg.IsDevelopmentMode) { - BackupMinecraftDataForRemoval(); + BackupMinecraftDataForRemoval(packageFamily); await DeploymentProgressWrapper(new PackageManager().RemovePackageAsync(pkg.Id.FullName, 0)); } else { Debug.WriteLine("Package is in development mode"); @@ -301,29 +300,29 @@ private string GetPackagePath(Package pkg) { } } - private async Task UnregisterPackage(string gameDir) { - foreach (var pkg in new PackageManager().FindPackages(MINECRAFT_PACKAGE_FAMILY)) { + private async Task UnregisterPackage(string packageFamily, string gameDir) { + foreach (var pkg in new PackageManager().FindPackages(packageFamily)) { string location = GetPackagePath(pkg); if (location == "" || location == gameDir) { - await RemovePackage(pkg); + await RemovePackage(pkg, packageFamily); } } } - private async Task ReRegisterPackage(string gameDir) { - foreach (var pkg in new PackageManager().FindPackages(MINECRAFT_PACKAGE_FAMILY)) { + private async Task ReRegisterPackage(string packageFamily, string gameDir) { + foreach (var pkg in new PackageManager().FindPackages(packageFamily)) { string location = GetPackagePath(pkg); if (location == gameDir) { Debug.WriteLine("Skipping package removal - same path: " + pkg.Id.FullName + " " + location); return; } - await RemovePackage(pkg); + await RemovePackage(pkg, packageFamily); } Debug.WriteLine("Registering package"); string manifestPath = Path.Combine(gameDir, "AppxManifest.xml"); await DeploymentProgressWrapper(new PackageManager().RegisterPackageAsync(new Uri(manifestPath), null, DeploymentOptions.DevelopmentMode)); Debug.WriteLine("App re-register done!"); - RestoreMinecraftDataFromReinstall(); + RestoreMinecraftDataFromReinstall(packageFamily); } private void InvokeDownload(Version v) { @@ -410,7 +409,7 @@ await downloader.Download(v.UUID, "1", dlPath, (current, total) => { private async Task Remove(Version v) { v.StateChangeInfo = new VersionStateChangeInfo(VersionState.Uninstalling); - await UnregisterPackage(Path.GetFullPath(v.GameDirectory)); + await UnregisterPackage(v.GamePackageFamily, Path.GetFullPath(v.GameDirectory)); Directory.Delete(v.GameDirectory, true); v.StateChangeInfo = null; if (v.IsImported) { @@ -483,8 +482,15 @@ private void MenuItemRefreshVersionListClicked(object sender, RoutedEventArgs e) } } + struct MinecraftPackageFamilies + { + public static readonly string MINECRAFT = "Microsoft.MinecraftUWP_8wekyb3d8bbwe"; + public static readonly string MINECRAFT_PREVIEW = "Microsoft.MinecraftWindowsBeta_8wekyb3d8bbwe"; + } + namespace WPFDataTypes { + public class NotifyPropertyChangedBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; @@ -553,6 +559,11 @@ public bool IsImported { public string GameDirectory { get; set; } + public string GamePackageFamily + { + get => VersionType == VersionType.Preview ? MinecraftPackageFamilies.MINECRAFT_PREVIEW : MinecraftPackageFamilies.MINECRAFT; + } + public bool IsInstalled => Directory.Exists(GameDirectory); public string DisplayName { From e6db663127da574d9e61e298ff22ee81f1c44b4f Mon Sep 17 00:00:00 2001 From: MCMrARM Date: Thu, 10 Feb 2022 16:19:03 +0100 Subject: [PATCH 3/5] Ignore unsupported version types --- MCLauncher/VersionList.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MCLauncher/VersionList.cs b/MCLauncher/VersionList.cs index c7debd1..ebd1240 100644 --- a/MCLauncher/VersionList.cs +++ b/MCLauncher/VersionList.cs @@ -49,7 +49,10 @@ private void ParseList(JArray data, bool isCache) { // ([name, uuid, versionType])[] foreach (JArray o in data.AsEnumerable().Reverse()) { bool isNew = dbVersions.Add(o[0].Value()) && !isCache; - Add(new WPFDataTypes.Version(o[1].Value(), o[0].Value(), (WPFDataTypes.VersionType) o[2].Value(), isNew, _commands)); + int versionType = o[2].Value(); + if (!Enum.IsDefined(typeof(WPFDataTypes.VersionType), versionType) || versionType == (int) WPFDataTypes.VersionType.Imported) + continue; + Add(new WPFDataTypes.Version(o[1].Value(), o[0].Value(), (WPFDataTypes.VersionType) versionType, isNew, _commands)); } } From a6a532557e2bc811690a218059d25f2fed077982 Mon Sep 17 00:00:00 2001 From: MCMrARM Date: Thu, 10 Feb 2022 20:55:48 +0100 Subject: [PATCH 4/5] Use Minecraft-Preview- prefix for preview builds This change is made so that in the case that Microsoft publishes a preview build with the same version as a beta build, the launcher is able to have both of these downloaded at once. --- MCLauncher/MainWindow.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCLauncher/MainWindow.xaml.cs b/MCLauncher/MainWindow.xaml.cs index e7c2a99..2baadb9 100644 --- a/MCLauncher/MainWindow.xaml.cs +++ b/MCLauncher/MainWindow.xaml.cs @@ -531,7 +531,7 @@ public Version(string uuid, string name, VersionType versionType, bool isNew, IC this.DownloadCommand = commands.DownloadCommand; this.LaunchCommand = commands.LaunchCommand; this.RemoveCommand = commands.RemoveCommand; - this.GameDirectory = "Minecraft-" + Name; + this.GameDirectory = (versionType == VersionType.Preview ? "Minecraft-Preview-" : "Minecraft-") + Name; } public Version(string name, string directory, ICommonVersionCommands commands) { this.UUID = UNKNOWN_UUID; From 8969534ecd598f7f942a77de93e0f55edba4b040 Mon Sep 17 00:00:00 2001 From: MCMrARM Date: Thu, 10 Feb 2022 20:58:27 +0100 Subject: [PATCH 5/5] Use the Minecraft-Preview- prefix for the Appx too --- MCLauncher/MainWindow.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCLauncher/MainWindow.xaml.cs b/MCLauncher/MainWindow.xaml.cs index 2baadb9..c273185 100644 --- a/MCLauncher/MainWindow.xaml.cs +++ b/MCLauncher/MainWindow.xaml.cs @@ -333,7 +333,7 @@ private void InvokeDownload(Version v) { Debug.WriteLine("Download start"); Task.Run(async () => { - string dlPath = "Minecraft-" + v.Name + ".Appx"; + string dlPath = (v.VersionType == VersionType.Preview ? "Minecraft-Preview-" : "Minecraft-") + v.Name + ".Appx"; VersionDownloader downloader = _anonVersionDownloader; if (v.VersionType == VersionType.Beta) { downloader = _userVersionDownloader;