Exemplo n.º 1
0
        public void TestZBSPatchingReal()
        {
            // create an instance
            TACTRepo tactRepo = new TACTRepo(@"D:\Backup\")
            {
                ConfigContainer = new ConfigContainer("wowt", Locale.US)
            };

            // open the configs
            tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory);

            // load the archives
            tactRepo.IndexContainer = new Indices.IndexContainer();
            tactRepo.IndexContainer.Open(tactRepo.BaseDirectory);

            // open the patch file
            tactRepo.PatchFile = new Patch.PatchFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.PatchEKey);

            // get the seagiant2.m2 patch
            Assert.IsTrue(tactRepo.PatchFile.TryGet(new Cryptography.MD5Hash("8fbb9c89e91e0b30ab5eeec1cee0666d"), out var patchEntry));

            // read the patch entry from the archives
            // load the original file from disk - build 27826
            // apply the ZBSPatch (patch entry) to the original
            // verify the produced output is byte identical with the patched model - build 28807
            using (var original = File.OpenRead("Resources/seagiant2_27826.m2"))
                using (var output = new MemoryStream())
                {
                    Assert.IsTrue(tactRepo.PatchFile.ApplyPatch(patchEntry, tactRepo.IndexContainer, original, output));

                    var b = File.ReadAllBytes("Resources/seagiant2_28807.m2");
                    Assert.IsTrue(b.SequenceEqual(output.ToArray()));
                }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Removes a CASRecord
        /// </summary>
        /// <param name="record"></param>
        public bool Remove(CASRecord record, TACTRepo tactRepo = null)
        {
            if (record == null)
            {
                return(false);
            }

            if (_CKeyEntries.TryGetValue(record.CKey, out var entry))
            {
                _CKeyEntries.Remove(record.CKey);
                _EKeyEntries.Remove(entry.EKey);

                // propagate removal
                if (tactRepo != null)
                {
                    tactRepo.IndexContainer?.Remove(entry.EKey);
                    tactRepo.DownloadFile?.Remove(entry.EKey);
                    tactRepo.DownloadSizeFile?.Remove(entry.EKey);
                }

                return(true);
            }

            return(false);
        }
Exemplo n.º 3
0
        public void OverrideExistingFile_Simple()
        {
            // This is "simple" as I only have the Encoding, Root and configs downloaded - no CDN backup.
            // By using CDNClient all of this can be achieved without any source files on disk.

            string customfilepath = "Resources/ui_mainmenu_legion_27826.m2";                                               // local filename
            string targetfilename = "interface/glues/models/ui_mainmenu_battleforazeroth/ui_mainmenu_battleforazeroth.m2"; // root filename
            uint   targetfileid   = 2021650;                                                                               // filedataid of the above

            TACTRepo tactRepo = new TACTRepo(@"C:\wamp64\www")
            {
                ConfigContainer = new ConfigContainer("wow", Locale.EU)
            };

            // open the configs
            // note: the Patch file is removed since it isn't accessible (aka downloaded)
            tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory);

            // update the cdns config to point to localhost
            var hosts = tactRepo.ConfigContainer.CDNsFile.GetValue("hosts", Locale.EU);

            if (!hosts.Contains("127.0.0.1"))
            {
                tactRepo.ConfigContainer.CDNsFile.SetValue("hosts", hosts.Insert(0, "127.0.0.1 "), Locale.EU);
            }

            var servers = tactRepo.ConfigContainer.CDNsFile.GetValue("servers", Locale.EU);

            if (!servers.Contains("http://127.0.0.1"))
            {
                tactRepo.ConfigContainer.CDNsFile.SetValue("servers", hosts.Insert(0, "http://127.0.0.1 "), Locale.EU);
            }

            // create an index container
            tactRepo.IndexContainer = new Indices.IndexContainer();

            // open encoding
            tactRepo.EncodingFile = new Encoding.EncodingFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.EncodingEKey);

            // open root
            tactRepo.EncodingFile.TryGetCKeyEntry(tactRepo.ConfigContainer.RootCKey, out var rootCKeyEntry);
            tactRepo.RootFile = new Root.RootFile(tactRepo.BaseDirectory, rootCKeyEntry.EKey)
            {
                FileLookup = new MockFileLookup()
                {
                    [targetfilename] = targetfileid // mock the custom file
                }
            };

            // encode and export the "custom" file to a temp folder
            // - one must export otherwise the file won't be added to an archive
            var blte = BlockTable.BlockTableEncoder.EncodeAndExport(customfilepath, "test", targetfilename);

            // add the "custom" file to root, this will propagate via 'tactRepo'
            tactRepo.RootFile.AddOrUpdate(blte, tactRepo);

            // save the repo
            tactRepo.Save(tactRepo.BaseDirectory);
        }
Exemplo n.º 4
0
        public MPQReader(Options options, TACTRepo tactrepo, IList <string> patchArchives)
        {
            Options  = options;
            TACTRepo = tactrepo;
            FileList = new ConcurrentDictionary <string, CASRecord>(StringComparer.OrdinalIgnoreCase);

            PatchArchives = new Queue <string>(patchArchives);
            DataDirectory = Path.DirectorySeparatorChar + "DATA" + Path.DirectorySeparatorChar;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Adds a CASRecord, this will overwrite existing entries
        /// </summary>
        /// <param name="record"></param>
        /// <param name="repo"></param>
        public override void AddOrUpdate(CASRecord record, TACTRepo repo = null)
        {
            var entry = new DownloadSizeFileEntry()
            {
                EKey           = record.EKey,
                CompressedSize = record.EBlock.CompressedSize,
            };

            AddOrUpdate(entry, record.Tags);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Saves the DownloadFile to disk and optionally updates the BuildConfig
        /// </summary>
        /// <param name="directory">Root Directory</param>
        /// <param name="configContainer"></param>
        /// <returns></returns>
        public override CASRecord Write(string directory, TACTRepo tactRepo = null)
        {
            CASRecord record;

            using (var bt = new BlockTableStreamWriter(_EncodingMap[0]))
                using (var bw = new BinaryWriter(bt))
                {
                    // Header
                    DownloadHeader.EntryCount = (uint)_FileEntries.Count;
                    DownloadHeader.TagCount   = (ushort)_TagEntries.Count;
                    DownloadHeader.Write(bw);

                    // File Entries
                    bt.AddBlock(_EncodingMap[1]);
                    foreach (var fileEntry in _FileEntries.Values.OrderBy(x => x.Priority))
                    {
                        fileEntry.Write(bw, DownloadHeader);
                    }

                    // Tag Entries
                    bt.AddBlock(_EncodingMap[2]);
                    WriteTags(bw, _FileEntries.Count);

                    // finalise
                    record = bt.Finalise();

                    // save
                    string saveLocation = Helpers.GetCDNPath(record.EKey.ToString(), "data", directory, true);
                    using (var fs = File.Create(saveLocation))
                    {
                        bt.WriteTo(fs);
                        record.BLTEPath = saveLocation;
                    }
                }

            if (tactRepo != null)
            {
                // insert the record into the encoding
                tactRepo.EncodingFile?.AddOrUpdate(record);

                // update the build config with the new values
                if (tactRepo.ConfigContainer?.BuildConfig != null)
                {
                    tactRepo.ConfigContainer.BuildConfig.SetValue("download-size", record.EBlock.DecompressedSize, 0);
                    tactRepo.ConfigContainer.BuildConfig.SetValue("download-size", record.EBlock.CompressedSize, 1);
                    tactRepo.ConfigContainer.BuildConfig.SetValue("download", record.CKey, 0);
                    tactRepo.ConfigContainer.BuildConfig.SetValue("download", record.EKey, 1);
                }
            }

            Checksum = record.CKey;
            FilePath = record.BLTEPath;
            return(record);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Saves the EncodingFile to disk and optionally updates the BuildConfig
        /// </summary>
        /// <param name="directory">Root Directory</param>
        /// <param name="configContainer"></param>
        /// <returns></returns>
        public CASRecord Write(string directory, TACTRepo repo = null)
        {
            if (Partial)
            {
                throw new NotSupportedException("Writing is not supported for partial EncodingFiles");
            }

            CASRecord record;

            using (var bt = new BlockTableStreamWriter(_EncodingMap[1], 1))
                using (var bw = new BinaryWriter(bt))
                {
                    // ESpecStringTable 1
                    bt.Write(string.Join('\0', ESpecStringTable).GetBytes());
                    EncodingHeader.ESpecTableSize = (uint)bt.Length;

                    // CKeysPageIndices 2, CKeysPageTable 3
                    WritePage(bw, 2, EncodingHeader.CKeyPageSize << 10, _CKeyEntries);

                    // EKeysPageIndices 4, EKeysPageTable 5
                    WritePage(bw, 4, EncodingHeader.EKeyPageSize << 10, _EKeyEntries);

                    // Header 0
                    bt.AddBlock(_EncodingMap[0], 0);
                    EncodingHeader.Write(bw);

                    // File ESpec 6
                    bt.AddBlock(_EncodingMap[6], 6);
                    bt.Write(GetFileESpec(bt.SubStreams).GetBytes());

                    // finalise
                    record = bt.Finalise();

                    // save
                    string saveLocation = Helpers.GetCDNPath(record.EKey.ToString(), "data", directory, true);
                    using var fs = File.Create(saveLocation);
                    bt.WriteTo(fs);
                    record.BLTEPath = saveLocation;
                }

            // update the build config with the new values
            if (repo?.ConfigContainer?.BuildConfig != null)
            {
                repo.ConfigContainer.BuildConfig.SetValue("encoding-size", record.EBlock.DecompressedSize, 0);
                repo.ConfigContainer.BuildConfig.SetValue("encoding-size", record.EBlock.CompressedSize, 1);
                repo.ConfigContainer.BuildConfig.SetValue("encoding", record.CKey, 0);
                repo.ConfigContainer.BuildConfig.SetValue("encoding", record.EKey, 1);
            }

            Checksum = record.CKey;
            FilePath = record.BLTEPath;
            return(record);
        }
Exemplo n.º 8
0
        public DirectoryReader(Options options, TACTRepo tactrepo)
        {
            DataArchives  = new List <string>(0x100);
            BaseArchives  = new List <string>(0x40);
            PatchArchives = new List <string>(0x40);

            Options       = options;
            TACTRepo      = tactrepo;
            BaseDirectory = options.WoWDirectory;

            PopulateCollections();
        }
Exemplo n.º 9
0
        /// <summary>
        /// Adds a CASRecord to the InstallFile, this will overwrite existing entries
        /// </summary>
        /// <param name="record"></param>
        /// <param name="tactRepo">If provided, will add the entry to all relevant system files</param>
        /// <param name="tags"></param>
        public void AddOrUpdate(CASRecord record, TACTRepo tactRepo = null)
        {
            var entry = new InstallFileEntry()
            {
                FilePath         = record.FileName,
                CKey             = record.CKey,
                DecompressedSize = record.EBlock.DecompressedSize,
            };

            AddOrUpdate(entry, record.Tags);

            // add the record to the Encoding File
            tactRepo?.EncodingFile?.AddOrUpdate(record, tactRepo);
        }
Exemplo n.º 10
0
        public void TestConfigs()
        {
            TACTRepo tactRepo = new TACTRepo()
            {
                ConfigContainer = new ConfigContainer("wowt", Locale.US)
            };

            //configContainer.OpenRemote(@"D:\Backup\");
            //Assert.IsNotNull(configContainer.VersionsFile);

            tactRepo.ConfigContainer.OpenLocal(@"D:\Backup\");
            Assert.IsNotNull(tactRepo.ConfigContainer.VersionsFile);
            Assert.IsNotNull(tactRepo.ConfigContainer.BuildConfig);
            Assert.IsFalse(tactRepo.ConfigContainer.RootCKey.IsEmpty);
        }
Exemplo n.º 11
0
        public void CreateNewTactRepo()
        {
            if (Directory.Exists(@"C:\wamp64\www\tpr"))
            {
                Directory.Delete(@"C:\wamp64\www\tpr", true);
            }
            if (Directory.Exists(@"C:\wamp64\www\wow"))
            {
                Directory.Delete(@"C:\wamp64\www\wow", true);
            }

            string buildName   = "WOW-15595patch4.3.4_Retail";
            string buildId     = "15595";
            string versionName = "4.3.4.15595";

            string tempPath = Path.Combine("test", "temp");

            Directory.CreateDirectory(tempPath);

            // open a new tact instance
            TACTRepo tactRepo = new TACTRepo("test");

            tactRepo.Create("wow", Locale.US, uint.Parse(buildId));

            // update the configs
            // build info and server locations
            tactRepo.ManifestContainer.VersionsFile.SetValue("BuildId", buildId);
            tactRepo.ManifestContainer.VersionsFile.SetValue("VersionsName", versionName);
            tactRepo.ConfigContainer.BuildConfig.SetValue("Build-Name", buildName, 0);
            tactRepo.ConfigContainer.BuildConfig.SetValue("Build-UID", "wow", 0);
            tactRepo.ConfigContainer.BuildConfig.SetValue("Build-Product", "WoW", 0);
            tactRepo.ManifestContainer.CDNsFile.SetValue("Hosts", "localhost");
            tactRepo.ManifestContainer.CDNsFile.SetValue("Servers", "http://127.0.0.1");

            // set root variables
            tactRepo.RootFile.LocaleFlags = Root.LocaleFlags.enUS;
            tactRepo.RootFile.FileLookup  = new MockFileLookup();
            tactRepo.RootFile.AddBlock(Root.LocaleFlags.All_WoW, 0);

            var record = BlockTable.BlockTableEncoder.EncodeAndExport("Resources/seagiant2_27826.m2", tempPath, "creature/seagiant2/seagiant2.m2");

            tactRepo.RootFile.AddOrUpdate(record, tactRepo);

            record.FileName = "WoW.exe";
            tactRepo.InstallFile.AddOrUpdate(record, tactRepo);

            tactRepo.Save(tactRepo.BaseDirectory, tactRepo.BaseDirectory);
        }
Exemplo n.º 12
0
        public void TestOpenFile()
        {
            // create an instance
            TACTRepo tactRepo = new TACTRepo(PATH)
            {
                ManifestContainer = new ManifestContainer("wow", Locale.US),
                ConfigContainer   = new ConfigContainer()
            };

            // open the configs
            tactRepo.ManifestContainer.OpenLocal(MANIFEST_PATH);
            tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory, tactRepo.ManifestContainer);

            // load the archives
            tactRepo.IndexContainer = new Indices.IndexContainer();
            tactRepo.IndexContainer.Open(tactRepo.BaseDirectory);
            Assert.IsTrue(tactRepo.IndexContainer.DataIndices.Any());

            // open the encoding
            tactRepo.EncodingFile = new Encoding.EncodingFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.EncodingEKey);

            // get the root ckey
            Assert.IsTrue(tactRepo.EncodingFile.TryGetCKeyEntry(tactRepo.ConfigContainer.RootCKey, out var rootCEntry));

            // open the root
            tactRepo.RootFile = new Root.RootFile(tactRepo.BaseDirectory, rootCEntry.EKeys[0]);

            // read a normal file then an encrypted file
            string[] filenames = new[] { "world/arttest/boxtest/xyz.m2", "creature/encrypted05/encrypted05.m2" };
            foreach (var filename in filenames)
            {
                // open a stream to the file
                // gets the file's ckey from the root
                // gets the file's ekey from the encoding
                // loads the IndexEntry from the IndexContainer
                // returns a BLTE stream to the file segment in the data blob
                using (var fs = tactRepo.RootFile.OpenFile(filename, tactRepo))
                {
                    Assert.IsNotNull(fs);

                    byte[] buffer = new byte[4];
                    fs.Read(buffer);

                    // check for MD21 magic
                    Assert.AreEqual(BitConverter.ToUInt32(buffer), 0x3132444Du);
                }
            }
        }
Exemplo n.º 13
0
        public void TestConfigs()
        {
            TACTRepo tactRepo = new TACTRepo("wow", Locale.US, MANIFEST_PATH, PATH)
            {
                ManifestContainer = new ManifestContainer("wow", Locale.US),
                ConfigContainer   = new ConfigContainer()
            };

            //configContainer.OpenRemote(PATH);
            //Assert.IsNotNull(configContainer.VersionsFile);

            tactRepo.ManifestContainer.OpenLocal(MANIFEST_PATH);
            tactRepo.ConfigContainer.OpenLocal(PATH, tactRepo.ManifestContainer);
            Assert.IsNotNull(tactRepo.ManifestContainer.VersionsFile);
            Assert.IsNotNull(tactRepo.ConfigContainer.BuildConfig);
            Assert.IsFalse(tactRepo.ConfigContainer.RootCKey.IsEmpty);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Adds a CASRecord, this will overwrite existing entries
        /// </summary>
        /// <param name="record"></param>
        /// <param name="repo"></param>
        public override void AddOrUpdate(CASRecord record, TACTRepo repo = null)
        {
            // prevent overflow for old versions
            if (DownloadHeader.BasePriority + record.DownloadPriority < 0)
            {
                record.DownloadPriority = 0;
            }

            var entry = new DownloadFileEntry()
            {
                EKey           = record.EKey,
                CompressedSize = record.EBlock.CompressedSize,
                Flags          = new byte[DownloadHeader.FlagSize],
                Priority       = record.DownloadPriority,
                Checksum       = 0 // TODO do we know what this is?
            };

            AddOrUpdate(entry, record.Tags);
        }
Exemplo n.º 15
0
        private static void PopulateRootFile(TACTRepo repo, DirectoryReader dirReader, MPQReader mpqReader)
        {
            Log.WriteLine("Extracting Data files");

            // load files from mpqs, patches and loose files in the data directory
            mpqReader.FileList.Clear();
            mpqReader.EnumerateDataArchives(dirReader.DataArchives);
            mpqReader.EnumeratePatchArchives();
            //mpqReader.EnumerateLooseDataFiles(dirReader.GetLooseDataFiles());

            Log.WriteLine("Populating Root file");
            mpqReader.Process <RootFile>((x) =>
            {
                repo.RootFile.AddOrUpdate(x);
                repo.EncodingFile.AddOrUpdate(x);
                repo.IndexContainer.Enqueue(x);
                repo.DownloadFile.AddOrUpdate(x);
            });
        }
Exemplo n.º 16
0
        /// <summary>
        /// Adds a CASRecord to the InstallFile, this will overwrite existing entries
        /// </summary>
        /// <param name="record"></param>
        /// <param name="tactRepo">If provided, will add the entry to all relevant system files</param>
        /// <param name="tags"></param>
        public void AddOrUpdate(CASRecord record, TACTRepo tactRepo = null)
        {
            var entry = new InstallFileEntry()
            {
                FilePath         = record.FileName,
                CKey             = record.CKey,
                DecompressedSize = record.EBlock.DecompressedSize,
            };

            AddOrUpdate(entry, record.Tags);

            // add the record to all referenced files
            if (tactRepo != null)
            {
                tactRepo.EncodingFile?.AddOrUpdate(record);
                tactRepo.IndexContainer?.Enqueue(record);
                tactRepo.DownloadFile?.AddOrUpdate(record, 2);
                tactRepo.DownloadSizeFile?.AddOrUpdate(record);
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Adds a CASRecord to the EncodingFile generating all required entries. This will overwrite existing entries
        /// </summary>
        /// <param name="record"></param>
        public void AddOrUpdate(CASRecord record, TACTRepo tactRepo = null)
        {
            // CKeyPageTable
            Remove(record, tactRepo);
            var cKeyEntry = new EncodingContentEntry
            {
                CKey             = record.CKey,
                EKeys            = new List <MD5Hash>(),
                DecompressedSize = record.EBlock.DecompressedSize,
            };

            cKeyEntry.EKeys.Add(record.EKey);
            _CKeyEntries.Add(record.CKey, cKeyEntry);

            // get or add to the ESpecStringTable
            int especIndex = ESpecStringTable.IndexOf(record.ESpec);

            if (especIndex == -1)
            {
                especIndex = ESpecStringTable.Count - 2;
                ESpecStringTable.Insert(especIndex, record.ESpec);
            }

            // EKeyPageTable
            var eKeyEntry = new EncodingEncodedEntry()
            {
                CompressedSize = record.EBlock.CompressedSize,
                EKey           = record.EKey,
                ESpecIndex     = (uint)especIndex
            };

            _EKeyEntries[record.EKey] = eKeyEntry;

            // propogate the new record
            if (tactRepo != null)
            {
                tactRepo.IndexContainer?.Enqueue(record);
                tactRepo.DownloadFile?.AddOrUpdate(record);
                tactRepo.DownloadSizeFile?.AddOrUpdate(record);
            }
        }
Exemplo n.º 18
0
        private static void PopulateInstallFile(TACTRepo repo, DirectoryReader dirReader, MPQReader mpqReader)
        {
            Log.WriteLine("Extracting and Populating Install file");

            // use base-*.mpq if available else enumerate all non-archived files not inside the data folder
            // this ignores temp data folders e.g. wdb, wtf, cache etc
            if (dirReader.BaseArchives.Count == 0)
            {
                dirReader.ExportFiles();
            }
            else
            {
                mpqReader.EnumerateDataArchives(dirReader.BaseArchives, true);
                mpqReader.Process <InstallFile>((x) =>
                {
                    repo.InstallFile.AddOrUpdate(x);
                    repo.EncodingFile.AddOrUpdate(x);
                    repo.IndexContainer.Enqueue(x);
                    repo.DownloadFile.AddOrUpdate(x);
                });
            }
        }
Exemplo n.º 19
0
 public abstract CASRecord Write(string directory, TACTRepo tactRepo = null);
Exemplo n.º 20
0
        static void Main(string[] args)
        {
            if (args.Length < 4)
            {
                throw new ArgumentException("Required arguments: cdndir, buildconfig, cdnconfig, outdir");
            }

            var cdndir = args[0];
            var bc     = args[1];
            var cdnc   = args[2];
            var outdir = args[3];

            var mapFilter = "";

            if (args.Length == 5)
            {
                mapFilter = args[4];
            }

            // Open storage for specific build
            TACTRepo tactRepo = new TACTRepo(cdndir)
            {
                ConfigContainer = new ConfigContainer()
            };

            Console.WriteLine("Loading configs..");
            tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory, bc, cdnc);

            Console.WriteLine("Loading indices..");
            tactRepo.IndexContainer = new TACT.Net.Indices.IndexContainer();
            tactRepo.IndexContainer.Open(tactRepo.BaseDirectory, tactRepo.ConfigContainer);

            Console.WriteLine("Loading encoding..");
            tactRepo.EncodingFile = new TACT.Net.Encoding.EncodingFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.EncodingEKey);

            Console.WriteLine("Looking up root..");
            tactRepo.EncodingFile.TryGetCKeyEntry(tactRepo.ConfigContainer.RootCKey, out var rootCEntry);

            Console.WriteLine("Loading root..");
            tactRepo.RootFile = new TACT.Net.Root.RootFile(tactRepo.BaseDirectory, rootCEntry.EKey);

            Console.WriteLine("Loading TACT keys..");
            try
            {
                using (var client = new HttpClient())
                {
                    var result = client.GetAsync("https://wow.tools/api.php?type=tactkeys").Result;
                    var keys   = result.Content.ReadAsStringAsync().Result.Split('\n');
                    foreach (var key in keys)
                    {
                        var split = key.Split(' ');
                        if (split.Length < 2)
                        {
                            continue;
                        }

                        var keyname  = Convert.ToUInt64(split[0], 16);
                        var keybytes = split[1];
                        if (TACT.Net.Cryptography.KeyService.TryAddKey(keyname, keybytes))
                        {
                            Console.WriteLine("Added TACT key " + split[0]);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("An error occurred retrieving/loading TACT keys: " + e.Message);
            }

            // Set up DBCD
            var dbdProvider = new GithubDBDProvider();
            var dbcProvider = new TACTDBCProvider(tactRepo);
            var dbcd        = new DBCD.DBCD(dbcProvider, dbdProvider);

            // Open Map DBC with local defs
            Console.WriteLine("Opening Map.db2..");

            // This will currently crash on partially encrypted DBs with unknown keys due to https://github.com/wowdev/TACT.Net/issues/12
            var mapdb = dbcd.Load("Map");

            // Run through map db
            Console.WriteLine("Extracting tiles..");

            foreach (dynamic map in mapdb.Values)
            {
                if (!string.IsNullOrEmpty(mapFilter) && map.Directory != mapFilter)
                {
                    continue;
                }

                Console.WriteLine(map.Directory);

                // Load WDT
                Stream wdtStream;

                try
                {
                    if (map.WdtFileDataID == 0)
                    {
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine("Skipping map " + map.Directory + " with no WDT!");
                        Console.ResetColor();
                        continue;
                    }

                    wdtStream = tactRepo.RootFile.OpenFile((uint)map.WdtFileDataID, tactRepo);
                }
                catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException e)
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Older build detected: map record has no wdtFileDataID property");
                    Console.ResetColor();
                    wdtStream = tactRepo.RootFile.OpenFile("world/maps/" + map.Directory + "/" + map.Directory + ".wdt", tactRepo);
                }

                if (wdtStream == null)
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Skipping map " + map.Directory + " with unshipped WDT!");
                    Console.ResetColor();
                    continue;
                }

                var minimapFDIDs = WDT.FileDataIdsFromWDT(wdtStream);
                if (minimapFDIDs.Count() == 0)
                {
                    // Pre-MAID build, extract by filename
                    for (var x = 0; x < 64; x++)
                    {
                        for (var y = 0; y < 64; y++)
                        {
                            string tileName      = "world/minimaps/" + map.Directory + "/map" + x.ToString().PadLeft(2, '0') + "_" + y.ToString().PadLeft(2, '0') + ".blp";
                            var    minimapStream = tactRepo.RootFile.OpenFile(tileName, tactRepo);
                            if (minimapStream == null)
                            {
                                continue;
                            }

                            var minimapName = "map" + x.ToString().PadLeft(2, '0') + "_" + y.ToString().PadLeft(2, '0') + ".blp";
                            var minimapPath = Path.Combine(outdir, "world", "minimaps", map.Directory, minimapName);

                            Directory.CreateDirectory(Path.GetDirectoryName(minimapPath));

                            using (var fileStream = File.Create(minimapPath))
                            {
                                minimapStream.CopyTo(fileStream);
                            }
                        }
                    }
                }
                else
                {
                    // Extract tiles by FDID
                    minimapFDIDs = minimapFDIDs.Where(chunk => chunk.fileDataId != 0).ToArray();
                    foreach (var minimap in minimapFDIDs)
                    {
                        var minimapStream = tactRepo.RootFile.OpenFile(minimap.fileDataId, tactRepo);
                        if (minimapStream == null)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine("Unable to extract minimap " + minimap.fileDataId + " for tile " + minimap.x + "_" + minimap.y);
                            Console.ResetColor();
                            continue;
                        }

                        var minimapName = "map" + minimap.x.ToString().PadLeft(2, '0') + "_" + minimap.y.ToString().PadLeft(2, '0') + ".blp";
                        var minimapPath = Path.Combine(outdir, "world", "minimaps", map.Directory, minimapName);

                        Directory.CreateDirectory(Path.GetDirectoryName(minimapPath));

                        using (var fileStream = File.Create(minimapPath))
                        {
                            minimapStream.CopyTo(fileStream);
                        }
                    }
                }
            }

            // Append any filenames from listfile for additional non-WDT referenced minimaps?
        }
Exemplo n.º 21
0
 public abstract void AddOrUpdate(CASRecord record, TACTRepo repo = null);
Exemplo n.º 22
0
 public TACTDBCProvider(TACTRepo tactRepo)
 {
     this.tactRepo = tactRepo;
 }
Exemplo n.º 23
0
 public CASRecord Write(string directory, TACTRepo tactRepo = null)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 24
0
        public static string MANIFEST_PATH; // = CdnRootDir + @"\wow";



        static void Main(string[] args)
        {
            string      seetingsDir = Directory.GetCurrentDirectory() + "/AppSettings.json";
            AppSettings settings    = null;

            try
            {
                FileStream f            = new FileStream(seetingsDir, FileMode.Open, FileAccess.Read, FileShare.Read);
                var        streamReader = new StreamReader(f, Encoding.UTF8);
                settings = JsonConvert.DeserializeObject <AppSettings>(streamReader.ReadToEnd());
            }
            catch (Exception e)
            {
                settings = new AppSettings
                {
                    cdnRootDir = "",

                    mysqlUser        = "******",
                    mysqlPassword    = "******",
                    dataFolderPath   = Directory.GetCurrentDirectory() + "\\Data\\",
                    exportFolderPath = Directory.GetCurrentDirectory() + "\\DataExport\\",
                    databaseName     = "tacthost",
                    databaseAdress   = "localhost"
                };

                string json = JsonConvert.SerializeObject(settings, Formatting.Indented);
                File.WriteAllText(seetingsDir, json);
            }

            CDN_DATA_DIR  = settings.cdnRootDir + @"tpr\wow";
            MANIFEST_PATH = settings.cdnRootDir + @"wow";

            var tactRepo = new TACTRepo(CDN_DATA_DIR)
            {
                ManifestContainer = new ManifestContainer("wow", Locale.EU),
                ConfigContainer   = new ConfigContainer()
            };

            tactRepo.ManifestContainer.OpenLocal(MANIFEST_PATH);

            tactRepo.ConfigContainer.OpenLocal(tactRepo.BaseDirectory, tactRepo.ManifestContainer);

            tactRepo.IndexContainer = new Net.Indices.IndexContainer();
            tactRepo.IndexContainer.Open(tactRepo.BaseDirectory);


            tactRepo.EncodingFile = new Net.Encoding.EncodingFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.EncodingEKey);
            tactRepo.EncodingFile.TryGetCKeyEntry(tactRepo.ConfigContainer.RootCKey, out var rootCEntry);
            tactRepo.RootFile     = new Net.Root.RootFile(tactRepo.BaseDirectory, rootCEntry.EKey);
            tactRepo.InstallFile  = new InstallFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.InstallEKey);
            tactRepo.DownloadFile = new Net.Download.DownloadFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.DownloadEKey);
            tactRepo.PatchFile    = new Net.Patch.PatchFile(tactRepo.BaseDirectory, tactRepo.ConfigContainer.PatchEKey);

            tactRepo.RootFile.FileLookup = new ListFileLookup();

            string[] files = Directory.GetFiles(settings.dataFolderPath, "*", SearchOption.AllDirectories);
            for (int i = 0; i < files.Length; i++)
            {
                files[i] = files[i].Replace(settings.dataFolderPath, "");
            }

            Console.WriteLine("Found " + files.Length + " Files to proccess in " + settings.dataFolderPath);



            foreach (string s in files)
            {
                string filename = s.Substring(s.LastIndexOf("\\") + 1);
                string path     = s.Substring(0, s.LastIndexOf("\\") + 1);


                LocaleFlags locale = LocaleFlags.All_WoW;

                if (path.ToLower().Contains("dbfilesclient"))
                {
                    var match        = Regex.Match(path, @"(frFR)|(enUS)|(ptBR)|(ruRU)|(esES)|(esMX)|(itIT)|(deDE)|(enGB)|(ptPT)");
                    var pathSplit    = path.Split("\\");
                    var localeString = "";
                    foreach (var split in pathSplit)
                    {
                        if (split.Contains(match.Value))
                        {
                            locale       = (LocaleFlags)Enum.Parse(typeof(LocaleFlags), split);
                            localeString = split;
                            path         = path.Replace("\\" + localeString, "");
                            break;
                        }
                    }
                }



                CASRecord record = BlockTableEncoder.EncodeAndExport(settings.dataFolderPath + s, settings.exportFolderPath, (path + filename).Replace("\\", "/"));



                uint fId = tactRepo.RootFile.FileLookup.GetOrCreateFileId(record.FileName);

                Console.WriteLine("Added " + filename + " with ID: " + fId);

                tactRepo.RootFile.AddOrUpdate(record, tactRepo, locale);
                tactRepo.InstallFile.AddOrUpdate(record, tactRepo);
            }



            tactRepo.Save(tactRepo.BaseDirectory, settings.cdnRootDir);
        }
Exemplo n.º 25
0
 public void AddOrUpdate(CASRecord record, TACTRepo repo = null)
 {
     throw new NotImplementedException();
 }