예제 #1
0
        public void BuildCABMap(string[] blks)
        {
            // the cab map is comprised of an array of paths followed by a map of cab identifiers to indices into that path array
            // it would be more correct to load only the required mhy0 from the .blk, but i'm lazy
            // TODO: this should be moved into library code and not gui code, also should be made async
            using (var mapFile = File.Create("cabMap.bin"))
            {
                using (var mapWriter = new BinaryWriter(mapFile))
                {
                    int collisions = 0;
                    var cabMapInt  = new Dictionary <Guid, int>();
                    cabMap.Clear();
                    mapWriter.Write(blks.Length);
                    for (int i = 0; i < blks.Length; i++)
                    {
                        Logger.Info(String.Format("processing blk {0}/{1} ({2})", i + 1, blks.Length, blks[i]));
                        Progress.Report(i + 1, blks.Length);
                        mapWriter.Write(blks[i]);

                        var blkFile = new BlkFile(new FileReader(blks[i]));
                        foreach (var mhy0 in blkFile.Files)
                        {
                            if (mhy0.ID == Guid.Empty)
                            {
                                continue;
                            }
                            if (cabMap.ContainsKey(mhy0.ID))
                            {
                                //throw new InvalidDataException("mhy0 id collision found");
                                // i don't think i can do much about this
                                // colliding mhy0s appear to just contain the same data anyways...
                                //Logger.Warning(String.Format("mhy0 id collision! {0} {1}", mhy0.ID, cabDuplicateMap[mhy0.ID]));
                                collisions++;
                                continue;
                            }
                            cabMapInt.Add(mhy0.ID, i);
                            cabMap.Add(mhy0.ID, blks[i]);
                        }
                    }
                    mapWriter.Write(cabMap.Count);
                    foreach (var mapEntry in cabMapInt)
                    {
                        mapWriter.Write(mapEntry.Key.ToByteArray()); // ToByteArray has a weird order
                        mapWriter.Write(mapEntry.Value);
                    }
                    Logger.Info(String.Format("finished processing {0} blks with {1} cabs and {2} id collisions", blks.Length, cabMap.Count, collisions));
                }
            }
        }
예제 #2
0
        private void LoadBlkFile(FileReader reader, Guid?targetId = null)
        {
            if (targetId == null)
            {
                Logger.Info("Loading " + reader.FileName);
            }
            else
            {
                Logger.Info("Loading " + reader.FileName + " with target ID " + targetId.Value.ToString());
            }
            try
            {
                var  blkFile     = new BlkFile(reader);
                bool targetFound = false;
                for (int i = 0; i < blkFile.Files.Count; i++)
                {
                    //Console.WriteLine(blkFile.Files[i].ID);
                    if (targetId.HasValue && targetId.Value != blkFile.Files[i].ID)
                    {
                        continue;
                    }
                    targetFound = true;
                    // TODO: proper dummyPath
                    var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath),
                                                 string.Format("{0}_{1}", reader.FileName, blkFile.Files[i].ID.ToString()));
                    var subReader = new FileReader(dummyPath, new MemoryStream(blkFile.Files[i].Data));
                    var asset     = LoadAssetsFromMemory(subReader, dummyPath);
                    if (asset == null)
                    {
                        //Logger.Error("what");
                        continue;
                    }
                    foreach (var sharedFile in asset.m_Externals)
                    {
                        var sharedFileName       = sharedFile.fileName;
                        var sharedFileNameWithID = string.Format("{0}_{1}", sharedFileName, sharedFile.cabId.ToString());

                        if (!sharedFileName.EndsWith(".blk"))
                        {
                            // this will directly load .blk files, so anything that isn't one is not supported
                            Logger.Warning(String.Format("attempted to load non-blk shared file ({0})", sharedFileName));
                            continue;
                        }

                        if (!importFilesHash.Contains(sharedFileNameWithID))
                        {
                            var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
                            if (!File.Exists(sharedFilePath))
                            {
                                var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
                                if (findFiles.Length > 0)
                                {
                                    sharedFilePath = findFiles[0];
                                }
                            }

                            if (File.Exists(sharedFilePath))
                            {
                                // TODO: proper integration with the loading bar
                                LoadBlkFile(new FileReader(sharedFilePath), sharedFile.cabId);
                                //importFiles.Add(sharedFilePath);
                                importFilesHash.Add(sharedFileNameWithID);
                            }
                        }
                    }
                }
                if (blkFile.Files.Count > 0 && !targetFound)
                {
                    Logger.Warning("failed to find target mhy0");
                }
            }
            catch (Exception e)
            {
                Logger.Error($"Error while reading blk file {reader.FileName}", e);
            }
            finally
            {
                reader.Dispose();
            }
        }