public ApplicationPackageManifest(ClientHandler client, ProductHandler_Tank tankHandler, Stream stream, string name) { ClientCreateArgs_Tank args = client.CreateArgs.HandlerArgs as ClientCreateArgs_Tank ?? new ClientCreateArgs_Tank(); var cmf = tankHandler.m_rootContentManifest; using (BinaryReader reader = new BinaryReader(stream)) { m_header = reader.Read <APMHeader>(); if (m_header.m_buildVersion >= 12923648 || m_header.m_buildVersion < 52320) { throw new NotSupportedException("Overwatch 1.29 or earlier is not supported"); } m_entries = reader.ReadArray <Entry>(m_header.m_entryCount); m_packageEntries = reader.ReadArray <PackageEntry>(m_header.m_packageCount); if (!VerifyEntries(cmf)) { Logger.Debug("APM", "Entry hash invalid. IV may be wrong"); } m_packages = new PackageHeader[m_header.m_packageCount]; m_packageRecords = new PackageRecord[m_header.m_packageCount][]; m_packageBundles = new ulong[m_header.m_packageCount][]; int c = 0; using (PerfCounter _ = new PerfCounter("APM:LoadPackages")) Parallel.For(0, m_header.m_packageCount, new ParallelOptions { MaxDegreeOfParallelism = 4 }, i => { c++; if (c % 1000 == 0) { if (!Console.IsOutputRedirected) { Console.Out.Write($"Loading packages: {Math.Floor(c / (float)m_header.m_packageCount * 10000) / 100:F0}% ({c}/{m_header.m_packageCount})\r"); } } LoadPackage(i, client, cmf); }); if (!Console.IsOutputRedirected) { Console.Write(new string(' ', Console.WindowWidth - 1) + "\r"); } } }
public APM(Stream apmStream, LookupContentByKeyDelegate lookupContentByKey) { using (BinaryReader reader = new BinaryReader(apmStream)) { header = reader.Read <APMHeader>(); entries = new APMEntry[header.entryCount]; for (int i = 0; i < header.entryCount; ++i) { entries[i] = reader.Read <APMEntry>(); } packages = new APMPackage[header.packageCount]; indices = new PackageIndex[header.packageCount]; records = new PackageIndexRecord[header.packageCount][]; dependencies = new uint[header.packageCount][]; for (int i = 0; i < header.packageCount; ++i) { packages[i] = reader.Read <APMPackage>(); Stream indexStream = lookupContentByKey(packages[i].packageKey); using (BinaryReader indexReader = new BinaryReader(indexStream)) { indices[i] = indexReader.Read <PackageIndex>(); indexStream.Position = indices[i].recordsOffset; using (GZipStream recordStream = new GZipStream(indexStream, CompressionMode.Decompress, true)) using (BinaryReader recordReader = new BinaryReader(recordStream)) { PackageIndexRecord[] recs = new PackageIndexRecord[indices[i].numRecords]; for (int j = 0; j < indices[i].numRecords; ++j) { recs[j] = recordReader.Read <PackageIndexRecord>(); } records[i] = recs; } indexStream.Position = indices[i].depsOffset; uint[] deps = new uint[indices[i].numDeps]; for (int j = 0; j < indices[i].numDeps; ++j) { deps[j] = indexReader.ReadUInt32(); } dependencies[i] = deps; } indexStream.Close(); indexStream.Dispose(); } } }