|
@@ -4,13 +4,17 @@ using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
using System.ComponentModel;
|
|
|
+using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Text.Json;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
+using VeloeMinecraftLauncher.Entity.LauncherProfiles;
|
|
|
using VeloeMinecraftLauncher.Entity.VersionManifest;
|
|
|
-using VeloeMinecraftLauncher.MinecraftLauncher;
|
|
|
+using VeloeMinecraftLauncher.Utils;
|
|
|
using VeloeMinecraftLauncher.Models.Entity;
|
|
|
+using VeloeMinecraftLauncher.Entity.Version;
|
|
|
+using System.Diagnostics;
|
|
|
|
|
|
namespace VeloeMinecraftLauncher.ViewModels;
|
|
|
|
|
@@ -33,15 +37,27 @@ public class VersionsDownloaderViewModel : ViewModelBase
|
|
|
private long _maxprogressvalue = 100;
|
|
|
private string _downloadingFileName = "No active downloads";
|
|
|
private string _tasksStatusLine = "No tasks started yet";
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Token source for downloading tasks
|
|
|
+ /// </summary>
|
|
|
private CancellationTokenSource _tokenSource = new();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Token source for checking downloading options on selection from verions available for downloading
|
|
|
+ /// </summary>
|
|
|
private CancellationTokenSource _filteredVersionTokenSource = new();
|
|
|
|
|
|
Serilog.ILogger _logger;
|
|
|
|
|
|
ObservableCollection<Entity.VersionManifest.Version> _filteredVersions;
|
|
|
+ ObservableCollection<DownloadedVersion> _downloadedVersions;
|
|
|
ObservableCollection<Modpack> _modpackVersions;
|
|
|
+ ObservableCollection<TreeNode> _downloadedVersionTree;
|
|
|
+ TreeNode _libraries;
|
|
|
List<Entity.VersionManifest.Version> _modpackVersionsAsVersion;
|
|
|
Entity.VersionManifest.Version _filteredVersion;
|
|
|
+ DownloadedVersion _downloadedVersion;
|
|
|
Modpack? _selectedModpack;
|
|
|
VersionManifest _versionManifest;
|
|
|
|
|
@@ -61,12 +77,21 @@ public class VersionsDownloaderViewModel : ViewModelBase
|
|
|
{
|
|
|
_modpackVersions = new();
|
|
|
}
|
|
|
+ if (DownloadedVersionTree is null)
|
|
|
+ {
|
|
|
+ _downloadedVersionTree = new();
|
|
|
+ }
|
|
|
+ if (DownloadedVersionsDictionary is null)
|
|
|
+ {
|
|
|
+ DownloadedVersionsDictionary = new();
|
|
|
+ }
|
|
|
_logger.Debug("Getting versionManifest.json");
|
|
|
_versionManifest = await Downloader.DownloadAndDeserializeJsonData<VersionManifest>("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json") ?? new();
|
|
|
_modpackVersions.AddRange(await Downloader.DownloadAndDeserializeJsonData<List<Modpack>>("https://files.veloe.link/launcher/modpacks.json") ?? new());
|
|
|
_modpackVersionsAsVersion = _modpackVersions.Select(v=> new Entity.VersionManifest.Version() { Id = v.Name, Type = "modpack", ComplianceLevel = v.Revision}).ToList();
|
|
|
_logger.Debug("Updating available versions to download.");
|
|
|
UpdateList();
|
|
|
+ SearchGameFolderForVersions();
|
|
|
IsControlsEnabled = true;
|
|
|
});
|
|
|
}
|
|
@@ -167,12 +192,366 @@ public class VersionsDownloaderViewModel : ViewModelBase
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public DownloadedVersion DownloadedVersion
|
|
|
+ {
|
|
|
+ get => _downloadedVersion;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ this.RaiseAndSetIfChanged(ref _downloadedVersion, value);
|
|
|
+ Task.Run(() =>
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ IsControlsEnabled = false;
|
|
|
+ DownloadedVersionTree.Clear();
|
|
|
+ DownloadedVersionTree = new();
|
|
|
+ this.RaisePropertyChanged(nameof(DownloadedVersionTree));
|
|
|
+ DownloadedVersionsDictionary.Clear();
|
|
|
+
|
|
|
+ if (value is null)
|
|
|
+ {
|
|
|
+ IsControlsEnabled = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Entity.Version.Version? version = null;
|
|
|
+
|
|
|
+ foreach (var dversion in DownloadedVersions)
|
|
|
+ {
|
|
|
+ string json;
|
|
|
+ using (StreamReader reader = new StreamReader(dversion.path))
|
|
|
+ {
|
|
|
+ json = reader.ReadToEnd();
|
|
|
+ }
|
|
|
+
|
|
|
+ var versionObject = JsonSerializer.Deserialize<Entity.Version.Version>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
|
+ DownloadedVersionsDictionary.Add(dversion.version, versionObject);
|
|
|
+
|
|
|
+ if (dversion == _downloadedVersion)
|
|
|
+ {
|
|
|
+ version = versionObject;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (version is null)
|
|
|
+ {
|
|
|
+ OpenErrorWindow("Json file is invalid!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var versionDir = new FileInfo(value.path)?.Directory?.FullName;
|
|
|
+
|
|
|
+ if (versionDir is null)
|
|
|
+ {
|
|
|
+ OpenErrorWindow("Version folder is invalid!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //get version
|
|
|
+
|
|
|
+ DownloadedVersionTree.Add(new TreeNode() { Title = "Version: " + (version.InheritsFrom ?? version.Id) });
|
|
|
+
|
|
|
+ //calc Size
|
|
|
+
|
|
|
+ long allSize = 0;
|
|
|
+ string[] size_label = { "bytes", "KB", "MB", "GB" };
|
|
|
+ var dirInfo = new DirectoryInfo(versionDir);
|
|
|
+
|
|
|
+ foreach (var file in dirInfo.EnumerateFiles("*", SearchOption.AllDirectories))
|
|
|
+ { allSize += file.Length; }
|
|
|
+
|
|
|
+ if (version.InheritsFrom is null)
|
|
|
+ {
|
|
|
+ //TODO add subnodes with size
|
|
|
+ dirInfo = new DirectoryInfo(Settings.minecraftForlderPath);
|
|
|
+ foreach (var dir in dirInfo.GetDirectories())
|
|
|
+ {
|
|
|
+ if (dir.Name != ".mixin.out" &&
|
|
|
+ dir.Name != "assets" &&
|
|
|
+ dir.Name != "javaruntime" &&
|
|
|
+ dir.Name != "libraries" &&
|
|
|
+ dir.Name != "logs" &&
|
|
|
+ dir.Name != "versions")
|
|
|
+ foreach (var file in dir.EnumerateFiles("*", SearchOption.AllDirectories))
|
|
|
+ { allSize += file.Length; }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var file in dirInfo.GetFiles("*"))
|
|
|
+ {
|
|
|
+ if (!(file.Name.Contains("Veloe") &&
|
|
|
+ file.Name.Contains("log") &&
|
|
|
+ file.Name.Contains("exe")) &&
|
|
|
+ file.Name == "launcher_profiles.json")
|
|
|
+ allSize += file.Length;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var j = 0;
|
|
|
+ var result = (double)allSize;
|
|
|
+ while (j < size_label.Length && result > 1024)
|
|
|
+ {
|
|
|
+ result = result / 1024;
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+
|
|
|
+ DownloadedVersionTree.Add(new TreeNode() { Title = "Size: " + string.Format("{0:N2}", result) + " " + size_label[j] });
|
|
|
+
|
|
|
+ //calc Worlds
|
|
|
+
|
|
|
+ dirInfo = null;
|
|
|
+
|
|
|
+ if (version.InheritsFrom is null && Directory.Exists(Settings.minecraftForlderPath + "saves"))
|
|
|
+ dirInfo = new DirectoryInfo(Settings.minecraftForlderPath + "saves");
|
|
|
+ else
|
|
|
+ if (Directory.Exists(versionDir + "/saves"))
|
|
|
+ dirInfo = new DirectoryInfo(versionDir + "/saves");
|
|
|
+
|
|
|
+ if (dirInfo is not null)
|
|
|
+ {
|
|
|
+ var worldsTreeNode = new TreeNode() { Title = "Worlds: " + dirInfo.GetDirectories().Count() };
|
|
|
+
|
|
|
+ foreach (var world in dirInfo.GetDirectories())
|
|
|
+ { worldsTreeNode.SubNode.Add(new TreeNode() { Title = world.Name }); }
|
|
|
+
|
|
|
+ DownloadedVersionTree.Add(worldsTreeNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ //check modloader
|
|
|
+
|
|
|
+ var modsTreeNode = new TreeNode();
|
|
|
+
|
|
|
+ if (version.InheritsFrom is null)
|
|
|
+ modsTreeNode.Title = "Modloader: No";
|
|
|
+ else if (version.Libraries.Any(l => l.Downloads?.Artifact?.Url?.Contains("forge") ?? false))
|
|
|
+ modsTreeNode.Title = "Modloader: Forge";
|
|
|
+ else if (version.Libraries.Any(l => l.Name.Contains("fabric")))
|
|
|
+ modsTreeNode.Title = "Modloader: Fabric";
|
|
|
+
|
|
|
+ //get mods list
|
|
|
+
|
|
|
+ if (modsTreeNode.Title != "No" && Directory.Exists(versionDir + "/mods"))
|
|
|
+ {
|
|
|
+ dirInfo = new DirectoryInfo(versionDir + "/mods");
|
|
|
+
|
|
|
+ modsTreeNode.Title += " (" + dirInfo.EnumerateFiles("*.jar", SearchOption.TopDirectoryOnly).Count() + ")";
|
|
|
+ foreach (var mod in dirInfo.EnumerateFiles("*.jar", SearchOption.TopDirectoryOnly))
|
|
|
+ { modsTreeNode.SubNode.Add(new TreeNode() { Title = mod.Name }); }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ DownloadedVersionTree.Add(modsTreeNode);
|
|
|
+
|
|
|
+ //calc resourcepacks
|
|
|
+
|
|
|
+ dirInfo = null;
|
|
|
+
|
|
|
+ if (version.InheritsFrom is null && Directory.Exists(Settings.minecraftForlderPath + "resourcepacks"))
|
|
|
+ dirInfo = new DirectoryInfo(Settings.minecraftForlderPath + "resourcepacks");
|
|
|
+ else
|
|
|
+ if (Directory.Exists(versionDir + "/resourcepacks"))
|
|
|
+ dirInfo = new DirectoryInfo(versionDir + "/resourcepacks");
|
|
|
+
|
|
|
+ if (dirInfo is not null)
|
|
|
+ {
|
|
|
+ var resourcepacksTreeNode = new TreeNode();
|
|
|
+
|
|
|
+ resourcepacksTreeNode.Title = "Resoursepacks: " + (dirInfo?.GetDirectories()?.Count() + dirInfo?.GetFiles().Count() ?? 0).ToString();
|
|
|
+ foreach (var resourcepack in dirInfo?.GetFileSystemInfos())
|
|
|
+ { resourcepacksTreeNode.SubNode.Add(new TreeNode() { Title = resourcepack.Name }); }
|
|
|
+
|
|
|
+ DownloadedVersionTree.Add(resourcepacksTreeNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ //calc assets
|
|
|
+
|
|
|
+ var assetsFolderName = version.Assets;
|
|
|
+
|
|
|
+ if (version.Assets is null &&
|
|
|
+ version.InheritsFrom is not null &&
|
|
|
+ DownloadedVersionsDictionary.TryGetValue(version.InheritsFrom, out var outVersion) &&
|
|
|
+ outVersion?.Assets is not null)
|
|
|
+ {
|
|
|
+ assetsFolderName = outVersion.Assets;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Directory.Exists(Settings.minecraftForlderPath + "assets/" + assetsFolderName))
|
|
|
+ {
|
|
|
+ dirInfo = new DirectoryInfo(Settings.minecraftForlderPath + "assets/" + assetsFolderName);
|
|
|
+ allSize = 0;
|
|
|
+ foreach (var file in dirInfo.EnumerateFiles("*", SearchOption.AllDirectories))
|
|
|
+ { allSize += file.Length; }
|
|
|
+
|
|
|
+ j = 0;
|
|
|
+ result = (double)allSize;
|
|
|
+ while (j < size_label.Length && result > 1024)
|
|
|
+ {
|
|
|
+ result = result / 1024;
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+
|
|
|
+ var assetsTreeNode = new TreeNode();
|
|
|
+ var usedByVersionCount = 0;
|
|
|
+
|
|
|
+ foreach (var dictionaryVersion in DownloadedVersionsDictionary)
|
|
|
+ {
|
|
|
+ if ((dictionaryVersion.Value?.Assets == assetsFolderName &&
|
|
|
+ dictionaryVersion.Value?.InheritsFrom is null) ||
|
|
|
+ (dictionaryVersion.Value?.InheritsFrom is not null &&
|
|
|
+ DownloadedVersionsDictionary.TryGetValue(dictionaryVersion.Value.InheritsFrom, out outVersion) &&
|
|
|
+ outVersion?.Assets == assetsFolderName))
|
|
|
+ {
|
|
|
+ usedByVersionCount++;
|
|
|
+ assetsTreeNode.SubNode.Add(new TreeNode() { Title = dictionaryVersion.Key });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ assetsTreeNode.Title = "Assets: " + version.Assets + " (" + string.Format("{0:N2}", result) + " " + size_label[j] + ") (" + usedByVersionCount + ")";
|
|
|
+ DownloadedVersionTree.Add(assetsTreeNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ // calc libraries
|
|
|
+
|
|
|
+ var usedLibraries = version.Libraries;
|
|
|
+
|
|
|
+ var libTreeNode = new TreeNode();
|
|
|
+ libTreeNode.Title = "Libraries";
|
|
|
+
|
|
|
+ if (version.InheritsFrom is not null && DownloadedVersionsDictionary.TryGetValue(version.InheritsFrom, out outVersion) && outVersion is not null)
|
|
|
+ {
|
|
|
+ usedLibraries.AddRange(outVersion.Libraries);
|
|
|
+ }
|
|
|
+
|
|
|
+ usedLibraries =
|
|
|
+ usedLibraries
|
|
|
+ .Where(l =>
|
|
|
+ File.Exists(Path.Combine(Settings.minecraftForlderPath + "libraries/" + l.Downloads?.Artifact?.Path)) ||
|
|
|
+ File.Exists(Path.Combine(Settings.minecraftForlderPath + "libraries/" + l.Downloads?.Classifiers?.NativesLinux?.Path)) ||
|
|
|
+ File.Exists(Path.Combine(Settings.minecraftForlderPath + "libraries/" + l.Downloads?.Classifiers?.NativesWindows?.Path)) ||
|
|
|
+ File.Exists(Path.Combine(Settings.minecraftForlderPath + "libraries/" + l.Downloads?.Classifiers?.NativesWindows64?.Path)) ||
|
|
|
+ File.Exists(Path.Combine(Settings.minecraftForlderPath + "libraries/" + l.Downloads?.Classifiers?.NativesWindows32?.Path)) ||
|
|
|
+ File.Exists(Path.Combine(Settings.minecraftForlderPath + "libraries/" + StartCommandBuilder.GetLibPathFromName(l.Name, true)))
|
|
|
+ )
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ var libraries = GetLibrariesFromVersions(DownloadedVersionsDictionary)
|
|
|
+ .Where(v => usedLibraries.Any(u => v.Value.Name == u.Name))
|
|
|
+ .GroupBy(a => a.Value.Name)
|
|
|
+ .Select(g =>
|
|
|
+ {
|
|
|
+ return new {
|
|
|
+ Name = g.Key,
|
|
|
+ Count = g.Select(a => a.Key).Distinct().Count(),
|
|
|
+ Versions = g.Select(a => a.Key).Distinct(),
|
|
|
+ LibraryUniqueInstances = g.Select(a => a.Value).Distinct() //IEnumerable cause there can be several lib blocks with different rules in one version json
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ foreach (var lib in libraries)
|
|
|
+ {
|
|
|
+ var subLibTreeNode = new TreeNode()
|
|
|
+ {
|
|
|
+ Title = lib.Name + " (" + lib.Count + ")",
|
|
|
+ };
|
|
|
+
|
|
|
+ //if only one version uses it (selected version), then add path to lib in Tag for deletion
|
|
|
+ if (lib.Count == 1)
|
|
|
+ {
|
|
|
+ subLibTreeNode.Tag = lib.LibraryUniqueInstances.Where(l => l.Downloads?.Artifact?.Path is not null).Select(l => l.Downloads?.Artifact?.Path).FirstOrDefault() ?? string.Empty;
|
|
|
+ //if fabric library
|
|
|
+ if (File.Exists(Settings.minecraftForlderPath + "libraries/" + StartCommandBuilder.GetLibPathFromName(lib.Name,true)))
|
|
|
+ subLibTreeNode.Tag = StartCommandBuilder.GetLibPathFromName(lib.Name,true);
|
|
|
+ }
|
|
|
+
|
|
|
+ var subLibUsedVersionsTreeNodeHeader = new TreeNode() { Title = "Using in versions:" };
|
|
|
+
|
|
|
+ foreach (var ver in lib.Versions)
|
|
|
+ subLibUsedVersionsTreeNodeHeader.SubNode.Add(new TreeNode() { Title = ver });
|
|
|
+
|
|
|
+ if (subLibUsedVersionsTreeNodeHeader.SubNode.Count > 0)
|
|
|
+ subLibTreeNode.SubNode.Add(subLibUsedVersionsTreeNodeHeader);
|
|
|
+
|
|
|
+ if (lib.LibraryUniqueInstances.Any(l=>l.Natives is not null) || lib.LibraryUniqueInstances.Any(l=>l.Downloads?.Classifiers is not null))
|
|
|
+ {
|
|
|
+ var subLibNativesTreeNodeHeader = new TreeNode() { Title = "Natives:" };
|
|
|
+
|
|
|
+ //check classifiers
|
|
|
+ var libraryNativeInstance = lib.LibraryUniqueInstances.Where(l => l.Natives is not null || l.Downloads?.Classifiers is not null).First();
|
|
|
+
|
|
|
+ if (libraryNativeInstance.Downloads?.Classifiers?.NativesWindows is not null)
|
|
|
+ {
|
|
|
+ subLibNativesTreeNodeHeader.SubNode.Add(new TreeNode()
|
|
|
+ {
|
|
|
+ Title = Path.GetFileName(libraryNativeInstance.Downloads?.Classifiers?.NativesWindows.Path) ?? "No lib name",
|
|
|
+ Tag = lib.Count == 1 ? libraryNativeInstance.Downloads?.Classifiers?.NativesWindows?.Path ?? string.Empty : string.Empty
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (libraryNativeInstance.Downloads?.Classifiers?.NativesWindows32 is not null)
|
|
|
+ {
|
|
|
+ subLibNativesTreeNodeHeader.SubNode.Add(new TreeNode()
|
|
|
+ {
|
|
|
+ Title = Path.GetFileName(libraryNativeInstance.Downloads?.Classifiers?.NativesWindows32.Path) ?? "No lib name",
|
|
|
+ Tag = lib.Count == 1 ? libraryNativeInstance.Downloads?.Classifiers?.NativesWindows32?.Path ?? string.Empty : string.Empty
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (libraryNativeInstance.Downloads?.Classifiers?.NativesWindows64 is not null)
|
|
|
+ {
|
|
|
+ subLibNativesTreeNodeHeader.SubNode.Add(new TreeNode()
|
|
|
+ {
|
|
|
+ Title = Path.GetFileName(libraryNativeInstance.Downloads?.Classifiers?.NativesWindows64.Path) ?? "No lib name",
|
|
|
+ Tag = lib.Count == 1 ? libraryNativeInstance.Downloads?.Classifiers?.NativesWindows64?.Path ?? string.Empty : string.Empty
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (libraryNativeInstance.Downloads?.Classifiers?.NativesLinux is not null)
|
|
|
+ {
|
|
|
+ subLibNativesTreeNodeHeader.SubNode.Add(new TreeNode()
|
|
|
+ {
|
|
|
+ Title = Path.GetFileName(libraryNativeInstance.Downloads?.Classifiers?.NativesLinux.Path) ?? "No lib name",
|
|
|
+ Tag = lib.Count == 1 ? libraryNativeInstance.Downloads?.Classifiers?.NativesLinux?.Path ?? string.Empty : string.Empty
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ if (subLibNativesTreeNodeHeader.SubNode.Count > 0)
|
|
|
+ subLibTreeNode.SubNode.Add(subLibNativesTreeNodeHeader);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ libTreeNode.SubNode.Add(subLibTreeNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ _libraries = libTreeNode;
|
|
|
+ DownloadedVersionTree.Add(libTreeNode);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ this.RaisePropertyChanged(nameof(DownloadedVersionTree));
|
|
|
+ IsControlsEnabled = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public Dictionary<string,Entity.Version.Version?> DownloadedVersionsDictionary { get; set; }
|
|
|
+
|
|
|
public ObservableCollection<Entity.VersionManifest.Version> FilteredVersions
|
|
|
{
|
|
|
get => _filteredVersions;
|
|
|
set => this.RaiseAndSetIfChanged(ref _filteredVersions, value);
|
|
|
}
|
|
|
|
|
|
+ public ObservableCollection<DownloadedVersion> DownloadedVersions
|
|
|
+ {
|
|
|
+ get => _downloadedVersions;
|
|
|
+ set => this.RaiseAndSetIfChanged(ref _downloadedVersions, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ObservableCollection<TreeNode> DownloadedVersionTree
|
|
|
+ {
|
|
|
+ get => _downloadedVersionTree;
|
|
|
+ set => this.RaiseAndSetIfChanged(ref _downloadedVersionTree, value);
|
|
|
+ }
|
|
|
+
|
|
|
public string DownloadButtonText
|
|
|
{
|
|
|
get => _downloadButtonText;
|
|
@@ -347,7 +726,159 @@ public class VersionsDownloaderViewModel : ViewModelBase
|
|
|
InstallForgeOptifine,
|
|
|
InstallFabric);
|
|
|
}
|
|
|
- return TaskStatus.RanToCompletion; });
|
|
|
+
|
|
|
+ SearchGameFolderForVersions();
|
|
|
+ return TaskStatus.RanToCompletion;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task OnDeleteButtonClick()
|
|
|
+ {
|
|
|
+ await Task.Run(async () => {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ IsControlsEnabled = false;
|
|
|
+ DownloadedVersionTree.Clear();
|
|
|
+ DownloadedVersionTree = new();
|
|
|
+ this.RaisePropertyChanged(nameof(DownloadedVersionTree));
|
|
|
+ DownloadedVersionsDictionary.Clear();
|
|
|
+ DownloadedVersionsDictionary = new();
|
|
|
+
|
|
|
+ Entity.Version.Version? version = null;
|
|
|
+
|
|
|
+ foreach (var dversion in DownloadedVersions)
|
|
|
+ {
|
|
|
+ string json;
|
|
|
+ using (StreamReader reader = new StreamReader(dversion.path))
|
|
|
+ {
|
|
|
+ json = reader.ReadToEnd();
|
|
|
+ }
|
|
|
+
|
|
|
+ var versionObject = JsonSerializer.Deserialize<Entity.Version.Version>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
|
|
+ DownloadedVersionsDictionary.Add(dversion.version, versionObject);
|
|
|
+
|
|
|
+ if (dversion == _downloadedVersion)
|
|
|
+ {
|
|
|
+ version = versionObject;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (version is null)
|
|
|
+ {
|
|
|
+ OpenErrorWindow("Json file is invalid!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var versionDir = new FileInfo(DownloadedVersion.path)?.Directory?.FullName;
|
|
|
+
|
|
|
+ if (versionDir is null)
|
|
|
+ {
|
|
|
+ OpenErrorWindow("Version folder is invalid!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var dirInfo = new DirectoryInfo(versionDir);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (version.InheritsFrom is null && DownloadedVersionsDictionary.Where(v=>v.Value.InheritsFrom is null).Count() == 1)
|
|
|
+ {
|
|
|
+ //if vanilla
|
|
|
+ Debug.WriteLine("Vanilla root directories deleted!");
|
|
|
+
|
|
|
+ if (Directory.Exists(Settings.minecraftForlderPath + "saves"))
|
|
|
+ Directory.Delete(Settings.minecraftForlderPath + "saves", true);
|
|
|
+
|
|
|
+ if (Directory.Exists(Settings.minecraftForlderPath + "resourcepacks"))
|
|
|
+ Directory.Delete(Settings.minecraftForlderPath + "resourcepacks", true);
|
|
|
+
|
|
|
+ if (Directory.Exists(Settings.minecraftForlderPath + "shaderpacks"))
|
|
|
+ Directory.Delete(Settings.minecraftForlderPath + "shaderpacks", true);
|
|
|
+ }
|
|
|
+
|
|
|
+ //calc assets
|
|
|
+
|
|
|
+ var assetsFolderName = version.Assets;
|
|
|
+
|
|
|
+ if (version.Assets is null &&
|
|
|
+ version.InheritsFrom is not null &&
|
|
|
+ DownloadedVersionsDictionary.TryGetValue(version.InheritsFrom, out var outVersion) &&
|
|
|
+ outVersion?.Assets is not null)
|
|
|
+ {
|
|
|
+ assetsFolderName = outVersion.Assets;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Directory.Exists(Settings.minecraftForlderPath + "assets/" + assetsFolderName))
|
|
|
+ {
|
|
|
+ var usedByVersionCount = 0;
|
|
|
+
|
|
|
+ foreach (var dictionaryVersion in DownloadedVersionsDictionary)
|
|
|
+ {
|
|
|
+ if ((dictionaryVersion.Value?.Assets == assetsFolderName &&
|
|
|
+ dictionaryVersion.Value?.InheritsFrom is null) ||
|
|
|
+ (dictionaryVersion.Value?.InheritsFrom is not null &&
|
|
|
+ DownloadedVersionsDictionary.TryGetValue(dictionaryVersion.Value.InheritsFrom, out outVersion) &&
|
|
|
+ outVersion?.Assets == assetsFolderName))
|
|
|
+ {
|
|
|
+ usedByVersionCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //delete assets if only deleting version used it
|
|
|
+ if (usedByVersionCount == 1)
|
|
|
+ {
|
|
|
+ Debug.WriteLine(Settings.minecraftForlderPath + "assets/" + assetsFolderName);
|
|
|
+ Directory.Delete(Settings.minecraftForlderPath + "assets/" + assetsFolderName,true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // calc libraries
|
|
|
+ DeleteLibrariesFromTreeNode(_libraries);
|
|
|
+
|
|
|
+ // delete version dir
|
|
|
+ Debug.WriteLine(versionDir);
|
|
|
+ Directory.Delete(versionDir, true);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ OpenErrorWindow(ex);
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ SearchGameFolderForVersions();
|
|
|
+ IsControlsEnabled = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DeleteLibrariesFromTreeNode(TreeNode library)
|
|
|
+ {
|
|
|
+ foreach (var node in library.SubNode)
|
|
|
+ DeleteLibrariesFromTreeNode(node);
|
|
|
+
|
|
|
+ if (!string.IsNullOrEmpty(library.Tag))
|
|
|
+ {
|
|
|
+ var libFileInfo = new FileInfo(Settings.minecraftForlderPath + "libraries/" + library.Tag);
|
|
|
+ var libDir = libFileInfo.Directory;
|
|
|
+
|
|
|
+ if(libDir?.Exists == false)
|
|
|
+ {
|
|
|
+ Debug.WriteLine($"Directory {libDir.FullName} does not exists! Subnode: {library.Title}");
|
|
|
+ _logger.Warning($"Directory {libDir.FullName} does not exists!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (libDir?.GetFileSystemInfos().Count() > 1)
|
|
|
+ {
|
|
|
+ Debug.WriteLine(libFileInfo.FullName);
|
|
|
+ libFileInfo.Delete();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.WriteLine(libDir?.FullName);
|
|
|
+ libDir?.Delete(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void UpdateList()
|
|
@@ -368,6 +899,47 @@ public class VersionsDownloaderViewModel : ViewModelBase
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public void SearchGameFolderForVersions()
|
|
|
+ {
|
|
|
+ if (DownloadedVersions is null)
|
|
|
+ DownloadedVersions = new();
|
|
|
+
|
|
|
+ DownloadedVersions.Clear();
|
|
|
+ DownloadedVersions = new();
|
|
|
+
|
|
|
+ DirectoryInfo versions = new(Settings.minecraftForlderPath + "versions");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var dirs = versions.GetDirectories("*", SearchOption.TopDirectoryOnly);
|
|
|
+ LauncherProfiles profiles = new LauncherProfiles();
|
|
|
+ profiles.SelectedProfile = "NotImplemented";
|
|
|
+
|
|
|
+ foreach (var dir in dirs)
|
|
|
+ {
|
|
|
+ _logger.Debug("Checking folder {0}", dir.Name);
|
|
|
+ string checkedPath;
|
|
|
+ if (File.Exists(checkedPath = dir.FullName + "/" + dir.Name + ".json"))
|
|
|
+ {
|
|
|
+ _logger.Debug("Found version {0}", dir.Name);
|
|
|
+ DownloadedVersions.Add(new DownloadedVersion(checkedPath, dir.Name));
|
|
|
+ profiles.Profiles.Add($"Version {dir.Name}", new Profile() { Name = dir.Name, LastVersionId = dir.Name, LauncherVisibilityOnGameClose = "keep the launcher open" });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (DirectoryNotFoundException)
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(Settings.minecraftForlderPath + "versions");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnOpenForlder()
|
|
|
+ {
|
|
|
+ if (DownloadedVersion?.version is not null && Path.Exists(Settings.minecraftForlderPath + "versions/" + DownloadedVersion.version))
|
|
|
+ Process.Start(new System.Diagnostics.ProcessStartInfo() { FileName = Settings.minecraftForlderPath + "versions/" + DownloadedVersion.version, UseShellExecute = true });
|
|
|
+ }
|
|
|
+
|
|
|
public void OnClosing(object sender, CancelEventArgs args)
|
|
|
{
|
|
|
_tokenSource.Cancel();
|
|
@@ -375,4 +947,41 @@ public class VersionsDownloaderViewModel : ViewModelBase
|
|
|
_filteredVersionTokenSource.Cancel();
|
|
|
_filteredVersionTokenSource.Dispose();
|
|
|
}
|
|
|
+
|
|
|
+ public IEnumerable<KeyValuePair<string,Library>> GetLibrariesFromVersions(Dictionary<string, Entity.Version.Version?> versions)
|
|
|
+ {
|
|
|
+ foreach (var version in versions)
|
|
|
+ {
|
|
|
+ if (version.Value is null) continue;
|
|
|
+
|
|
|
+ if (version.Value.InheritsFrom is not null && versions.TryGetValue(version.Value.InheritsFrom,out var inheritVersion) && inheritVersion?.Libraries is not null)
|
|
|
+ {
|
|
|
+ foreach (var lib in inheritVersion.Libraries)
|
|
|
+ yield return new KeyValuePair<string, Library>(version.Key, lib);
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var lib in version.Value.Libraries)
|
|
|
+ yield return new KeyValuePair<string, Library>(version.Key,lib);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+public class TreeNode
|
|
|
+{
|
|
|
+ public TreeNode()
|
|
|
+ {
|
|
|
+ Title = "Default";
|
|
|
+ SubNode = new();
|
|
|
+ Tag = string.Empty;
|
|
|
+ }
|
|
|
+
|
|
|
+ public string Title { get; set; }
|
|
|
+ public string Tag { get; set; }
|
|
|
+
|
|
|
+ public List<TreeNode> SubNode { get; set; }
|
|
|
+
|
|
|
+ public override string ToString()
|
|
|
+ {
|
|
|
+ return Title;
|
|
|
+ }
|
|
|
}
|