Exemplo n.º 1
0
        public ProductHandler_Tank(ClientHandler client, Stream stream)
        {
            m_client = client;

            var clientArgs = client.CreateArgs.HandlerArgs as ClientCreateArgs_Tank ?? new ClientCreateArgs_Tank();

            using (BinaryReader reader = new BinaryReader(stream)) {
                string str = Encoding.ASCII.GetString(reader.ReadBytes((int)stream.Length));

                string[] array = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                if (ROOT_FILE_FIELD_ORDER_CHECK != array[0])
                {
                    throw new InvalidDataException($"ProductHandler_Tank: Root file field list mismatch ({array[0]})");
                }

                m_rootFiles = new RootFile[array.Length - 1];
                for (int i = 1; i < array.Length; i++)
                {
                    m_rootFiles[i - 1] = new RootFile(array[i].Split('|'));
                }
            }

            if (!clientArgs.LoadManifest)
            {
                return;
            }

            int totalAssetCount = 0;

            foreach (RootFile rootFile in m_rootFiles.Reverse())    // cmf first, then apm
            {
                string extension = Path.GetExtension(rootFile.FileName);
                if (extension != ".cmf" && extension != ".apm" && extension != ".trg")
                {
                    continue;
                }

                var manifestName     = Path.GetFileNameWithoutExtension(rootFile.FileName);
                var manifestFileName = Path.GetFileName(rootFile.FileName);

                if (!manifestName.Contains(clientArgs.ManifestRegion ?? REGION_DEV))
                {
                    continue;                                                                  // is a CN (china) CMF. todo: support this
                }
                var locale = GetManifestLocale(manifestName);

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (extension == ".cmf")
                {
                    bool speech = manifestName.Contains(SPEECH_MANIFEST_NAME);
                    bool text   = manifestName.Contains(TEXT_MANIFEST_NAME);

                    if (speech)
                    {
                        if (locale != client.CreateArgs.SpeechLanguage)
                        {
                            continue;
                        }
                    }
                    else if (locale != null)
                    {
                        // text or old root/text combo
                        if (locale != client.CreateArgs.TextLanguage)
                        {
                            continue;
                        }
                    }

                    ContentManifestFile cmf;
                    //using (Stream file = File.OpenWrite($"{manifestName}.cmf")) {
                    //    cmfStream.CopyTo(file);
                    //}
                    try {
                        using (Stream cmfStream = client.OpenCKey(rootFile.MD5))
                            cmf = new ContentManifestFile(client, cmfStream, manifestFileName);
                    } catch (CryptographicException) {
                        Logger.Error("CASC", OutdatedTACTLibErrorMessage);
                        if (Debugger.IsAttached)
                        {
                            Debugger.Break();
                        }
                        throw;
                    }
                    if (speech)
                    {
                        m_speechContentManifest = cmf;
                    }
                    else if (text)
                    {
                        m_textContentManifest = cmf;
                    }
                    else
                    {
                        m_rootContentManifest = cmf;
                    }
                    totalAssetCount += cmf.m_header.m_dataCount;
                }
                else if (extension == ".apm")
                {
                    if (locale != client.CreateArgs.TextLanguage)
                    {
                        continue;
                    }
                    using (Stream apmStream = client.OpenCKey(rootFile.MD5))
                        m_packageManifest = new ApplicationPackageManifest(client, this, apmStream, manifestName);
                }
                else if (extension == ".trg")
                {
                    try {
                        using (Stream trgStream = client.OpenCKey(rootFile.MD5)) {
                            //using (Stream file = File.OpenWrite($"{manifestName}.trg")) {
                            //    trgStream.CopyTo(file);
                            //}

                            m_resourceGraph = new ResourceGraph(client, trgStream, manifestFileName);
                        }
                    } catch (CryptographicException) {
                        Logger.Error("CASC", OutdatedTACTLibErrorMessage);
                        if (Debugger.IsAttached)
                        {
                            Debugger.Break();
                        }
                        throw;
                    }
                }
            }

            m_usingResourceGraph = m_rootContentManifest.m_header.m_buildVersion >= VERSION_148_PTR;
            m_assets             = new ConcurrentDictionary <ulong, Asset>(Environment.ProcessorCount + 2, totalAssetCount);

            if (!m_usingResourceGraph)
            {
                for (int i = 0; i < m_packageManifest.m_header.m_packageCount; i++)
                {
                    var records = m_packageManifest.m_packageRecords[i];

                    for (int j = 0; j < records.Length; j++)
                    {
                        var record = records[j];
                        //Console.Out.WriteLine($"{record.GUID:X8} {record.Unknown1} {record.Unknown2} {Manifests[0].ContentManifest.Exists(record.GUID)} {Manifests[1].ContentManifest.Exists(record.GUID)}");

                        if (m_assets.ContainsKey(record.m_GUID))
                        {
                            continue;
                        }
                        m_assets[record.m_GUID] = new Asset(i, j);
                    }
                }
            }

            RegisterCMFAssets(m_rootContentManifest, PACKAGE_IDX_FAKE_ROOT_CMF);
            RegisterCMFAssets(m_textContentManifest, PACKAGE_IDX_FAKE_TEXT_CMF);
            RegisterCMFAssets(m_speechContentManifest, PACKAGE_IDX_FAKE_SPEECH_CMF);

            if (m_usingResourceGraph)
            {
                m_hackedLookedUpBundles = new HashSet <ulong>();
                m_hackedBundleLookup    = new Dictionary <ulong, ulong>();
                DoBundleLookupHack();
            }
        }
Exemplo n.º 2
0
        public ProductHandler_Tank(ClientHandler client, Stream stream)
        {
            _client = client;

            var clientArgs = client.CreateArgs.HandlerArgs as ClientCreateArgs_Tank ?? new ClientCreateArgs_Tank();

            using (BinaryReader reader = new BinaryReader(stream)) {
                string str = Encoding.ASCII.GetString(reader.ReadBytes((int)stream.Length));

                string[] array = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                if (FieldOrderCheck != array[0])
                {
                    throw new InvalidDataException($"ProductHandler_Tank: Root file field list mismatch ({array[0]})");
                }

                RootFiles = new RootFile[array.Length - 1];
                for (int i = 1; i < array.Length; i++)
                {
                    RootFiles[i - 1] = new RootFile(array[i].Split('|'));
                }
            }

            if (!clientArgs.LoadManifest)
            {
                return;
            }

            int totalAssetCount = 0;

            foreach (RootFile rootFile in RootFiles.Reverse())    // cmf first, then apm
            {
                string extension = Path.GetExtension(rootFile.FileName);
                if (extension != ".cmf" && extension != ".apm")
                {
                    continue;
                }

                string manifestName = Path.GetFileNameWithoutExtension(rootFile.FileName);
                if (manifestName == null)
                {
                    throw new InvalidDataException();
                }

                if (!manifestName.Contains(RegionDev))
                {
                    continue;                                    // is a CN (china?) CMF. todo: support this
                }
                var locale = GetManifestLocale(manifestName);

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (extension == ".cmf")
                {
                    bool speech = manifestName.Contains(SpeechManifestName);

                    if (speech)
                    {
                        if (locale != client.CreateArgs.SpeechLanguage)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (locale != client.CreateArgs.TextLanguage)
                        {
                            continue;
                        }
                    }

                    ContentManifestFile cmf;
                    using (Stream cmfStream = client.OpenCKey(rootFile.MD5)) {
                        try {
                            cmf = new ContentManifestFile(client, cmfStream, $"{manifestName}.cmf");
                        } catch (CryptographicException) {
                            Logger.Error("CASC", "Fatal - CMF decryption failed. Please update TACTLib.");
                            if (Debugger.IsAttached)
                            {
                                Debugger.Break();
                            }
                            throw;
                        }
                    }
                    if (speech)
                    {
                        SpeechContentManifest = cmf;
                    }
                    else
                    {
                        MainContentManifest = cmf;
                    }
                    totalAssetCount += cmf.Header.DataCount;
                }
                else if (extension == ".apm")
                {
                    if (locale != client.CreateArgs.TextLanguage)
                    {
                        continue;
                    }
                    using (Stream apmStream = client.OpenCKey(rootFile.MD5)) {
                        PackageManifest = new ApplicationPackageManifest(client, this, apmStream, manifestName);
                    }
                }
            }

            Assets = new ConcurrentDictionary <ulong, Asset>(Environment.ProcessorCount + 2, totalAssetCount);

            for (int i = 0; i < PackageManifest.Header.PackageCount; i++)
            {
                var records = PackageManifest.Records[i];

                for (int j = 0; j < records.Length; j++)
                {
                    var record = records[j];
                    //Console.Out.WriteLine($"{record.GUID:X8} {record.Unknown1} {record.Unknown2} {Manifests[0].ContentManifest.Exists(record.GUID)} {Manifests[1].ContentManifest.Exists(record.GUID)}");

                    if (Assets.ContainsKey(record.GUID))
                    {
                        continue;
                    }
                    Assets[record.GUID] = new Asset(i, j);
                }
            }

            for (int i = 0; i < 2; i++)
            {
                ContentManifestFile contentManifestFile;

                int cmfId = -(i + 1);
                if (cmfId == -1)
                {
                    contentManifestFile = MainContentManifest;
                }
                else if (cmfId == -2)
                {
                    contentManifestFile = SpeechContentManifest;
                }
                else
                {
                    throw new Exception("wat");
                }
                // main = -1
                // speech = -2

                Parallel.For(0, contentManifestFile.HashList.Length, new ParallelOptions {
                    MaxDegreeOfParallelism = 4
                }, j => {
                    var cmfAsset = contentManifestFile.HashList[j];
                    if (Assets.ContainsKey(cmfAsset.GUID))
                    {
                        return;
                    }
                    Assets[cmfAsset.GUID] = new Asset(cmfId, j);
                });
            }
        }