Browse Source

added modpack version check, fix modpack reinstall

Veloe 2 years ago
parent
commit
0bf164fe81

+ 26 - 0
VeloeMinecraftLauncher/MinecraftLauncher/Downloader.cs

@@ -13,6 +13,7 @@ using VeloeMinecraftLauncher.ViewModels;
 using VeloeMinecraftLauncher.Views;
 using System.Collections.ObjectModel;
 using VeloeMinecraftLauncher.Models.Entity;
+using SkiaSharp;
 
 namespace VeloeMinecraftLauncher.MinecraftLauncher;
 
@@ -522,11 +523,36 @@ internal static class Downloader
             webClient.DownloadFileAsync(new System.Uri(modpackUrl), Settings.minecraftForlderPath + $"versions/{SelectedModpack.Name}.zip");
             waitWhileBisy(ref webClient);
 
+            FileStream stream = null;
+            if (Directory.Exists($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/mods"))
+            {
+                foreach (var file in Directory.GetFiles($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/mods"))
+                {
+                    try { stream = File.Open(file,FileMode.Open, FileAccess.Read, FileShare.None);}
+                    catch (IOException) { throw; }
+                    finally { stream?.Close(); }
+                }
+            }
+            if (Directory.Exists($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/config"))
+                foreach (var file in Directory.GetFiles($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/mods"))
+                {
+                    try { stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None); }
+                    catch (IOException) { throw; }
+                    finally { stream?.Close(); }
+                }
+
+            if (Directory.Exists($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/mods"))
+                Directory.Delete($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/mods", true);
+            if (Directory.Exists($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/config"))
+                Directory.Delete($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/config", true);
+
             Settings.logger.Debug("Extracting: {0}", $"{SelectedModpack.Name}.zip");
             DownloadingFileName($"Unpacking {SelectedModpack.Name}.zip");
             ZipFile.ExtractToDirectory($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}.zip", Settings.minecraftForlderPath + $"versions/{SelectedModpack.Name}", true);
             File.Delete($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}.zip");
 
+            File.WriteAllText($"{Settings.minecraftForlderPath}versions/{SelectedModpack.Name}/revision.json",JsonSerializer.Serialize(SelectedModpack.Revision));
+
             RemoveProgressBar(webClient);
 
             //Progress = 100;

+ 55 - 1
VeloeMinecraftLauncher/ViewModels/MainWindowViewModel.cs

@@ -26,6 +26,7 @@ using System.Collections.Generic;
 using VeloeMinecraftLauncher.Models.Entity;
 using VeloeMinecraftLauncher.Models;
 using System.Collections.Specialized;
+using System.Linq;
 
 namespace VeloeMinecraftLauncher.ViewModels;
 
@@ -183,8 +184,61 @@ public class MainWindowViewModel : ViewModelBase
             {
                 OpenErrorWindow(ex);
             }
-        });
+            try
+            {
+                _logger.Debug("Checking modpacks updates...");
+                var modpacksInfo = Downloader.DownloadAndDeserializeJsonData<List<Modpack>>("https://files.veloe.link/launcher/modpacks.json");
+                var installedModpacks = //DownloadedVersions.Where(v => modpacksInfo.Select(m => m.Name).Contains(v.version)).Join(modpacksInfo, (v, m) => v.version == m.);
+                    from downloadedVersion in DownloadedVersions
+                    join modpack in modpacksInfo on downloadedVersion.version equals modpack.Name
+                    select new
+                    {
+                        Name = downloadedVersion.version,
+                        Path = downloadedVersion.path,
+                        Revision = modpack.Revision
+                    };
+                var modpacksToUpdate = new List<string>();
+                var modpacksRevsionUnknown = new List<string>();
+
+                foreach (var modpack in installedModpacks)
+                {
+                    if (File.Exists(Path.GetDirectoryName(modpack.Path) + "/revision.json"))
+                    {
+                        try
+                        {
+                            if (modpack.Revision > JsonSerializer.Deserialize<int>(File.ReadAllText(Path.GetDirectoryName(modpack.Path) + "/revision.json")))
+                                modpacksToUpdate.Add(modpack.Name);
+                        }
+                        catch (Exception)
+                        {
+                            modpacksRevsionUnknown.Add(modpack.Name);
+                        }
+                    }
+                    else
+                        modpacksRevsionUnknown.Add(modpack.Name);
+                }
+                var message = string.Empty;
+                if (modpacksToUpdate.Any())
+                    message = $"Found updates for selected installed modpacks:{Environment.NewLine}    {string.Join($"{Environment.NewLine}    ", modpacksToUpdate)}";
 
+                if (modpacksRevsionUnknown.Any())
+                {
+                    if (!string.IsNullOrEmpty(message))
+                        message += Environment.NewLine;
+                    message += $"Can't get revision for selected installed modpacks:{Environment.NewLine}    {string.Join($"{Environment.NewLine}    ", modpacksRevsionUnknown)}{Environment.NewLine}Please update them for correct verion checking!";
+                }
+
+                if (!string.IsNullOrEmpty(message))
+                    OpenErrorWindow(message);
+
+                _logger.Debug("Checking modpacks updates finished successfully!");
+            }
+            catch (Exception ex)
+            {
+                OpenErrorWindow(ex);
+            }
+        });
+        
     }
 
     System.Timers.Timer _consoleOutputTimer = new(250);

+ 40 - 10
VeloeMinecraftLauncher/ViewModels/VersionsDownloaderViewModel.cs

@@ -8,7 +8,9 @@ using System.Collections.ObjectModel;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
+using System.Text.Json;
 using System.Threading.Tasks;
+using VeloeMinecraftLauncher.Entity.Version;
 using VeloeMinecraftLauncher.Entity.VersionManifest;
 using VeloeMinecraftLauncher.MinecraftLauncher;
 using VeloeMinecraftLauncher.Models.Entity;
@@ -18,7 +20,7 @@ namespace VeloeMinecraftLauncher.ViewModels;
 
 public class VersionsDownloaderViewModel : ViewModelBase
 {
-    private string _startButton = "Download";
+    private string _installModpackButtonText = "Download Modpack";
     private bool _showOld = false;
     private bool _showSnaps = false;
     private bool _installFabric = false;
@@ -127,7 +129,29 @@ public class VersionsDownloaderViewModel : ViewModelBase
     public Modpack SelectedModpack
     {
         get => _selectedModpack;
-        set => this.RaiseAndSetIfChanged(ref _selectedModpack, value);
+        set
+        {
+            try
+            {
+                if (System.IO.File.Exists(Settings.minecraftForlderPath + $"versions/{value.Name}/revision.json"))
+                {               
+                    if (value.Revision > JsonSerializer.Deserialize<int>(System.IO.File.ReadAllText(Settings.minecraftForlderPath + $"versions/{value.Name}/revision.json")))
+                        InstallModpackButtonText = "Update Modpack";
+                    else
+                        InstallModpackButtonText = "Reinstall Modpack";              
+                }
+                else
+                    if (System.IO.Directory.Exists($"{Settings.minecraftForlderPath}versions/{value.Name}") && System.IO.File.Exists($"{Settings.minecraftForlderPath}versions/{value.Name}/{value.Name}.json"))
+                        InstallModpackButtonText = "Update Modpack";
+                    else
+                        InstallModpackButtonText = "Download Modpack";
+            }
+            catch (Exception)
+            {
+                InstallModpackButtonText = "Update Modpack";
+            }
+            this.RaiseAndSetIfChanged(ref _selectedModpack, value); 
+        }
     }
 
     public ObservableCollection<Entity.VersionManifest.Version> FilteredVersions
@@ -142,10 +166,10 @@ public class VersionsDownloaderViewModel : ViewModelBase
         set => this.RaiseAndSetIfChanged(ref _modpackVersions, value);
     }
 
-    public string StartButton
+    public string InstallModpackButtonText
     {
-        get => _startButton; 
-        set => this.RaiseAndSetIfChanged(ref _startButton, value);
+        get => _installModpackButtonText; 
+        set => this.RaiseAndSetIfChanged(ref _installModpackButtonText, value);
     }
 
     public bool ShowOld
@@ -256,6 +280,7 @@ public class VersionsDownloaderViewModel : ViewModelBase
 
     public async Task OnStartBunttonClick()
     {
+#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
         Task.Run(() => {
 
             if (FilteredVersion is null)
@@ -278,12 +303,20 @@ public class VersionsDownloaderViewModel : ViewModelBase
                   InstallForgeOptifine,
                   InstallFabric);
         return TaskStatus.RanToCompletion; });
+#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
     }
   
     public async void OnStartModpackBunttonClick()
     {
+        if (SelectedModpack is null)
+            return;
+
         FilteredVersion = FilteredVersions.Where(x => x.Id == SelectedModpack.Version).FirstOrDefault();
 
+        if (FilteredVersion is null)
+            return;
+
+#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
         Task.Run(() => Downloader.StartDownloadModpack(
             value => DownloadingFileName = value,
             value => IsControlsEnabled = value,
@@ -296,6 +329,7 @@ public class VersionsDownloaderViewModel : ViewModelBase
             InstallForge = SelectedModpack.Forge,
             InstallOptifine = SelectedModpack.Optifine,
             InstallForgeOptifine = SelectedModpack.ForgeOptifine));
+#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
     }
 
     private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
@@ -312,11 +346,7 @@ public class VersionsDownloaderViewModel : ViewModelBase
             if (_versionManifest.Versions is null)
                 return;
 
-            foreach (var version in _versionManifest.Versions)
-            {
-                if (ShowSnaps && version.Type == "snapshot" || ShowOld && version.Type is ("old_alpha" or "old_beta") || version.Type == "release")
-                    FilteredVersions.Add(version);
-            }
+            FilteredVersions.AddRange(_versionManifest.Versions.Where(version => ShowSnaps && version.Type == "snapshot" || ShowOld && version.Type is ("old_alpha" or "old_beta") || version.Type == "release"));
         }
         catch (Exception ex)
         {

+ 22 - 2
VeloeMinecraftLauncher/ViewModels/ViewModelBase.cs

@@ -41,8 +41,7 @@ public class ViewModelBase : ReactiveValidationObject
         Exception? innerException;
         switch (ex)
         {
-            case JavaProcessException:
-            case WebException or Win32Exception:
+            case WebException or Win32Exception or JavaProcessException or IOException:
                 message = ex.Message;
                 Settings.logger.Error(ex.Message);
 
@@ -98,6 +97,27 @@ public class ViewModelBase : ReactiveValidationObject
                 });
             }
         });
+#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
+    }
+
+    public static void OpenErrorWindow(string message, string logfile = "")
+    {       
+#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
+        Dispatcher.UIThread.InvokeAsync(() =>
+        {
+            if (Application.Current is not null && Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            {
+                Dispatcher.UIThread.InvokeAsync(() =>
+                {
+                    var ErrorMessageViewModel = new ErrorWindowViewModel(message, logfile: logfile);
+                    var ErrorMessage = new ErrorWindow()
+                    {
+                        DataContext = ErrorMessageViewModel
+                    };
+                    ErrorMessage.ShowDialog(desktop.MainWindow);
+                });
+            }
+        });
 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
     }
 }

+ 2 - 2
VeloeMinecraftLauncher/Views/VersionsDownloader.axaml

@@ -50,9 +50,9 @@
 				<CheckBox IsChecked="{Binding InstallForge}" IsVisible="{Binding InstallForgeVisible}" IsEnabled="{Binding IsControlsEnabled}">Install Forge</CheckBox>
 				<CheckBox IsChecked="{Binding InstallForgeOptifine}" IsVisible="{Binding InstallForgeOptifineVisible}" IsEnabled="{Binding IsControlsEnabled}">Install Optifine (Mod)</CheckBox>
 				<CheckBox IsChecked="{Binding InstallOptifine}" IsVisible="{Binding InstallOptifineVisible}" IsEnabled="{Binding IsControlsEnabled}">Install Optifine (Vanilla)</CheckBox>
-				<Button Content="{Binding StartButton}" HorizontalAlignment="Center" Command="{Binding OnStartBunttonClick}" IsEnabled="{Binding IsControlsEnabled}"></Button>
+				<Button Content="Download" HorizontalAlignment="Center" Command="{Binding OnStartBunttonClick}" IsEnabled="{Binding IsControlsEnabled}"></Button>
 				<ComboBox Items="{Binding ModpackVersions}" PlaceholderText="Select pack" SelectedItem="{Binding SelectedModpack}" IsEnabled="{Binding IsControlsEnabled}" HorizontalAlignment="Stretch"></ComboBox>
-				<Button Content="Install Modpack" HorizontalAlignment="Center" Command="{Binding OnStartModpackBunttonClick}" IsEnabled="{Binding IsControlsEnabled}"></Button>
+				<Button Content="{Binding InstallModpackButtonText}" HorizontalAlignment="Center" Command="{Binding OnStartModpackBunttonClick}" IsEnabled="{Binding IsControlsEnabled}"></Button>
 				<ProgressBar Value="{Binding Progress}" ShowProgressText="true"></ProgressBar>
 				<TextBlock Text="{Binding DownloadingFileName}"></TextBlock>
 			</StackPanel>