using System.IO.Compression; using Mlaumcherb.Client.Avalonia.зримое; using Mlaumcherb.Client.Avalonia.классы; using Mlaumcherb.Client.Avalonia.холопы; namespace Mlaumcherb.Client.Avalonia.сеть.TaskFactories; public class ModpackDownloadTaskFactory : INetworkTaskFactory { INetworkTaskFactory _implementationVersion; private GameVersionDescriptor _descriptor; public ModpackDownloadTaskFactory(GameVersionDescriptor descriptor) { if(descriptor.modpack is null) throw new ArgumentNullException(nameof(descriptor.modpack)); _descriptor = descriptor; _implementationVersion = descriptor.modpack.format_version switch { 1 => new MyModpackV1DownloadTaskFactory(descriptor), _ => throw new Exception($"Unknown Modpack format_version: {descriptor.modpack.format_version}") }; } public Task CreateAsync(bool checkHashes) { // Modpacks can include libraries. // This libraries are downloaded in launcher_dir/libraries through symbolic link. var localLibsDir = Path.Concat(PathHelper.GetVersionDir(_descriptor.id), "libraries"); var globalLibsDir = PathHelper.GetLibrariesDir(); var dirInfo = new DirectoryInfo(localLibsDir.ToString()); // delete dir if it isn't symlink if(dirInfo.Exists && dirInfo.LinkTarget is null) dirInfo.Delete(true); if (!dirInfo.Exists) { LauncherApp.Logger.LogInfo(nameof(ModpackDownloadTaskFactory), $"Creating symbolic link '{localLibsDir}' -> '{globalLibsDir}'"); dirInfo.CreateAsSymbolicLink(globalLibsDir.ToString()); } return _implementationVersion.CreateAsync(checkHashes); } } public class MyModpackV1DownloadTaskFactory : INetworkTaskFactory { private readonly GameVersionDescriptor _descriptor; private IOPath _modpackDescriptorPath; private IOPath _versionDir; private MyModpackV1? _modpack; private HashSet _filesToDosnload = new(); public MyModpackV1DownloadTaskFactory(GameVersionDescriptor descriptor) { _descriptor = descriptor; _modpackDescriptorPath = PathHelper.GetModpackDescriptorPath(_descriptor.id); _versionDir = PathHelper.GetVersionDir(_descriptor.id); } public async Task CreateAsync(bool checkHashes) { if(_descriptor.modpack is null) throw new ArgumentNullException(nameof(_descriptor.modpack)); (_modpack, bool didDownloadModpackDescriptor) = await NetworkHelper.ReadOrDownloadAndDeserialize( _modpackDescriptorPath, _descriptor.modpack.artifact.url, _descriptor.modpack.artifact.sha1, checkHashes); if (_modpack.format_version != _descriptor.modpack.format_version) throw new Exception($"Modpack.format_version mismatches descriptor.modpack.version: " + $"{_modpack.format_version} != {_descriptor.modpack.format_version}"); NetworkTask? networkTask = null; if(!_modpack.CheckFiles(_versionDir, checkHashes, didDownloadModpackDescriptor, _filesToDosnload)) { networkTask = new NetworkTask( $"modpack '{_descriptor.assetIndex.id}'", _modpack.zip.size, Download ); } return networkTask; } private async Task Download(NetworkProgressReporter pr, CancellationToken ct) { LauncherApp.Logger.LogInfo(nameof(NetworkHelper), $"started downloading modpack '{_modpack!.name}'"); if(string.IsNullOrEmpty(_modpack.zip.url)) throw new Exception($"modpack '{_modpack.name}' doesn't have a url to download"); var _archivePath = Path.Concat(PathHelper.GetCacheDir(), "modpacks", _modpack.name + ".zip"); await NetworkHelper.DownloadFile(_modpack.zip.url, _archivePath, ct, pr.AddBytesCount); await using var zipf = File.OpenRead(_archivePath); using var archive = new ZipArchive(zipf); foreach (var entry in archive.Entries) { IOPath localPath = new(entry.FullName); if(_filesToDosnload.Contains(localPath)) { var real_path = Path.Concat(_versionDir, localPath); Directory.Create(real_path.ParentDir()); entry.ExtractToFile(real_path.ToString(), true); } } LauncherApp.Logger.LogInfo(nameof(NetworkHelper), $"finished downloading modpack '{_modpack.name}'"); } }