private void AddFilesFromManifest(Stream stream, Dictionary <int, int> baseIds) { List <Net.AssetDownloader.Asset> assets = new List <Net.AssetDownloader.Asset>(); var manifest = Dat.Manifest.Parse(stream); long size = 0; lock (baseIds) { foreach (var record in manifest.records) { int existing; if (!baseIds.TryGetValue(record.baseId, out existing)) { existing = 0; } if (existing != record.fileId) { baseIds[record.baseId] = record.fileId; Net.AssetDownloader.Asset asset; if (existing == 0) { asset = new Net.AssetDownloader.Asset(record.fileId, true, (int)(record.size * AVG_COMPRESSION + 0.5f)); } else { asset = new Net.AssetDownloader.Asset(existing, record.fileId, (int)(record.size * AVG_PATCH_COMPRESSION + 0.5f)); } asset.Complete += file_Complete; asset.Cancelled += file_Cancelled; asset.Progress += asset_Progress; assets.Add(asset); size += asset.size; } } progress.filesTotal += assets.Count; } if (assets.Count > 0) { lock (this) { progress.estimatedBytesRemaining += size; progress.estimatedTotalBytes += size; } downloader.Add(assets); } }
void downloader_Error(object sender, Net.AssetDownloader.Asset asset, Exception exception) { Util.Logging.Log(exception); lock (this) { if (progress.errored) { return; } progress.errored = true; } if (Error != null) { Error(this, "Failed to download files", exception); } }
private async Task <bool> GetManifests(int manifestId, int manifestSize, Dictionary <int, int> baseIds, bool rescan) { int existing; if (baseIds.TryGetValue(MANIFEST_BASE_ID, out existing) && existing == manifestId) { if (!rescan) { return(true); //the manifest is already up to date } } else if (rescan) { progress.rescan = false; } progress.manifestsTotal++; progress.estimatedBytesRemaining += manifestSize; progress.estimatedTotalBytes += manifestSize; int language; switch (Settings.BackgroundPatchingLang.Value) { case 1: //DE language = 296042; break; case 3: //FR language = 296043; break; case 2: //ES (n/a) case 0: //EN default: language = 296040; break; } #warning useCompression = BitConverter.IsLittleEndian var useCompression = BitConverter.IsLittleEndian; if (useCompression && archive == null) { archive = new Dat.Compression.Archive(); } //var asset = new Net.AssetDownloader.Asset(manifestId, false, manifestSize); var asset = new Net.AssetDownloader.Asset(manifestId, useCompression, useCompression ? (int)(manifestSize * AVG_COMPRESSION + 0.5f) : manifestSize); asset.Complete += delegate(object o, Net.AssetDownloader.Asset.CompleteEventArgs c) { progress.contentBytesCore += c.ContentLength; }; asset.Progress += asset_Progress; var cache = await downloader.Download(asset); using (cache) { if (cache != null && cache.HasData) { cache.SetPositionToContent(); var p = cache.Position; Dat.Manifest manifest; if (useCompression) { using (var ms = new MemoryStream(archive.DecompressRaw(cache, manifestSize))) { manifest = Tools.Dat.Manifest.Parse(ms); } } else { manifest = Tools.Dat.Manifest.Parse(cache); Create404Manifest(manifestId); } List <Net.AssetDownloader.Asset> assets = new List <Net.AssetDownloader.Asset>(manifest.records.Length); long size = 0; foreach (var record in manifest.records) { bool isUsed = true; switch (record.baseId) { case 724786: //Launcher break; case 1283391: //Launcher64 if (!Is64()) { isUsed = false; } break; case 1475411: //LauncherOSX isUsed = false; break; case 622855: //ClientContent86 break; case 1283393: //ClientContent64 break; case 296040: //English case 296042: //German case 296043: //French case 1051220: //Chinese isUsed = record.baseId == language; break; } //asset = new Net.AssetDownloader.Asset(record.fileId, !isUsed, !isUsed ? (int)(record.size * AVG_COMPRESSION + 0.5f) : record.size); asset = new Net.AssetDownloader.Asset(record.fileId, useCompression, useCompression ? (int)(record.size * AVG_COMPRESSION + 0.5f) : record.size); if (isUsed) { asset.Complete += manifestUsed_Complete; } else { asset.Complete += manifestUnused_Complete; } asset.Cancelled += manifest_Cancelled; asset.Progress += asset_Progress; assets.Add(asset); size += asset.size; } progress.manifestsTotal += assets.Count; progress.manifestsDownloaded++; progress.estimatedBytesRemaining += size; progress.estimatedTotalBytes += size; downloader.Add(assets); return(true); } } return(false); }
public async void Start(bool rescan) { lock (this) { if (IsActive) { return; } isActive = true; } Cache.Enabled = true; int lastBuild; if (!rescan && progress != null && progress.filesTotal > 0 && progress.filesDownloaded == progress.filesTotal) { lastBuild = progress.build; } else { lastBuild = 0; } progress = new DownloadProgressEventArgs(); progress.startTime = DateTime.UtcNow; progress.rescan = rescan; if (Starting != null) { Starting(this, EventArgs.Empty); } baseIds = await GetBaseIDs(); if (baseIds.Count > 0) { #region Initialize downloader try { if (downloader == null) { byte threads; if (Settings.BackgroundPatchingMaximumThreads.HasValue) { threads = Settings.BackgroundPatchingMaximumThreads.Value; } else { threads = 10; } downloader = new Net.AssetDownloader(threads); downloader.DownloadRate += downloader_DownloadRate; downloader.Error += downloader_Error; downloader.Complete += downloader_Complete; downloader.RequestComplete += downloader_RequestComplete; downloader.Tick += downloader_Tick; var v = Settings.PatchingSpeedLimit; if (v.HasValue) { downloader.BpsLimit = v.Value; } else { downloader.BpsLimit = Int32.MaxValue; } initializationTime = DateTime.UtcNow; } else if (DateTime.UtcNow.Subtract(initializationTime).TotalDays > 1) { downloader.SetIPPool(null); initializationTime = DateTime.UtcNow; } } catch (Exception e) { progress.errored = true; if (Error != null) { Error(this, "Failed to initialize", e); } isActive = false; if (StateChanged != null) { StateChanged(this, EventArgs.Empty); } return; } #endregion var latest = await GetLatest(); if (lastBuild > 0 && latest.buildId == lastBuild) { //nochange progress.build = latest.buildId; progress.filesTotal = progress.filesDownloaded = 1; if (Complete != null) { Complete(this, EventArgs.Empty); } } else if (latest.buildId != 0) { progress.build = latest.buildId; downloader.Start(); if (await GetManifests(latest.manifestId, latest.manifestSize, baseIds, rescan)) { if (progress.manifestsTotal > 0 || latest.buildId != Settings.LastKnownBuild.Value) { if (!progress.rescan) { if (PatchBeginning != null) { PatchBeginning(null, new PatchEventArgs() { Build = latest.buildId }); } lock (baseIds) progress.filesTotal++; var asset = new Net.AssetDownloader.Asset(latest.exeId, true, (int)(latest.exeSize * AVG_COMPRESSION + 0.5f)); lock (this) { progress.estimatedBytesRemaining += asset.size; progress.estimatedTotalBytes += asset.size; } asset.Cancelled += file_Cancelled; asset.Complete += file_Complete; asset.Progress += asset_Progress; asset.Complete += delegate(object o, Net.AssetDownloader.Asset.CompleteEventArgs c) { lock (this) { progress.contentBytesCore += c.ContentLength; } }; downloader.Add(asset); } } } else { progress.errored = true; if (Error != null) { Error(this, "Failed to retieve manifests", null); } } downloader.StopWhenComplete(); } else { progress.errored = true; if (Error != null) { Error(this, "Failed to retieve latest build", null); } } } else { progress.errored = true; if (Error != null) { Error(this, "Failed to read Gw2.dat", null); } } isActive = false; if (StateChanged != null) { StateChanged(this, EventArgs.Empty); } }