static private void putFilenameCacheEntry(ManifestEntry e, int i, Dictionary <string, List <int> > filenameEntryIndexDict) { List <int> indices; filenameEntryIndexDict.TryGetValue(e.filenameHashStr, out indices); if (indices == null) { indices = new List <int>(); filenameEntryIndexDict[e.filenameHashStr] = indices; } indices.Add(i); }
private AssetEntry getEntryForFileName(string filename, RequestCategory requestCategory = RequestCategory.NONE) { //logger.Debug("get entry for filename:" + filename + " with request category " + requestCategory); List <ManifestEntry> entries = Manifest.getEntriesForFilenameHash(Util.hashFileName(filename)); if (entries.Count() == 0) { // lets see if the filename is actually a hash (this shouldn't happen, but whatevers) entries = Manifest.getEntriesForFilenameHash(filename); if (entries.Count() == 0) { throw new Exception("Filename hash not found in manifest: '" + filename + "'"); } logger.Warn("Using filename[" + filename + "] as hash"); } // strip out duplicate patch paks entries.RemoveAll(e => { return(Manifest.getPAKName(e.pakIndex).Contains("patch") && entries.Any(x => x != e && x.idStr.Equals(e.idStr))); }); // logger.Debug("found " + entries.Count() + " entries in manifest that match"); string id = ""; if (entries.Count() == 1) { // if there was only one result, then use it id = entries.First().idStr; } else { ManifestEntry finalEntry = null; // work out which one we want based on the category string requestStr = requestCategory.ToString().ToLower(); //logger.Debug("multiple ids found for " + filename + ", using request category " + requestStr); foreach (ManifestEntry entry in entries) { //logger.Debug("[" + filename + "]: considering entry:" + entry + " :" + manifest.getPAKName(entry.pakIndex)); ManifestPAKFileEntry pak = Manifest.getPAK(entry.pakIndex); string pakName = pak.name; if (pakName.Contains(requestStr)) { finalEntry = entry; break; } } if (finalEntry == null) { // if we were still unable to break the tie logger.Error("tiebreak for " + filename + " no id match"); // one final check on the language, if an english one exists, use that over any other non-english one IEnumerable <ManifestEntry> engUni = entries.Where(e => e.lang == 0 || e.lang == 1); // if the number of english entries is different to the number of entries, then we should choose an english one and assume it is that one if (engUni.Count() > 0 && engUni.Count() != entries.Count()) { logger.Debug("tie broken with english language choice: " + finalEntry + " :" + Manifest.getPAKName(finalEntry.pakIndex)); finalEntry = engUni.First(); } else { // fail? String str = ""; foreach (ManifestEntry entry in entries) { str += "\t" + entry + " :" + Manifest.getPAKName(entry.pakIndex) + "\n"; } string errStr = ("Multiple ids match the filename [" + filename + "] but no request category was given, unable to determine which to return.\n" + str); throw new Exception(errStr); } } id = finalEntry.idStr; //logger.Debug("settled on entry:" + finalEntry + " :" + manifest.getPAKName(finalEntry.pakIndex)); } //logger.Debug("find asset file for id:" + id); AssetFile assetFile = FindAssetFileForId(id); //logger.Debug("result:" + assetFile); if (assetFile == null) { throw new Exception( "Filename found in manifest but unable to locate ID[" + id + "] in assets: '" + filename + "'"); } //logger.Debug("found with id:" + id); return(assetFile.getEntry(id)); }
private void processTable(byte[] manifestData) { //logger.Debug("process manifest table"); int tableOffset; int count; ManifestTableEntry a, b, c; int _256tableoffset; int _256; // See http://forum.xentax.com/viewtopic.php?f=17&t=10119 using (MemoryStream memStream = new MemoryStream(manifestData)) { using (BinaryReader dis = new BinaryReader(memStream)) { // read the manifest header byte[] twam = dis.ReadBytes(4); // These two are definitely version numbers ushort majorV = dis.ReadUInt16(); ushort minorV = dis.ReadUInt16(); _256tableoffset = dis.readInt(); _256 = dis.readInt(); a = new ManifestTableEntry("pak table", dis); b = new ManifestTableEntry("asset names", dis); c = new ManifestTableEntry("unk", dis); } } tableOffset = b.offset; count = b.count; // logger.Debug("read table 0"); // why is there a 256 table at the start? /** TABLE 0 - 256 byte table */ byte[] table = new byte[256]; for (int i = 0; i < _256; i++) { using (BinaryReader dis2 = new BinaryReader(new MemoryStream(manifestData, _256tableoffset + i, 1))) { table[i] = dis2.readByte(); } } /** TABLE 1 - PAK files */ // logger.Debug("read table 1"); for (int i = 0; i < a.count; i++) { using (BinaryReader dis2 = new BinaryReader( new MemoryStream(manifestData, a.offset + (i * a.stride), a.stride))) { pakFiles.Add(new ManifestPAKFileEntry(manifestData, dis2)); } } // logger.Debug("read table 3"); /** TABLE 3 - unknown? */ using (BinaryReader dis2 = new BinaryReader( new MemoryStream(manifestData, c.offset, c.tableSize))) { for (int i = 0; i < c.count; i++) { int ia = dis2.readInt() & 0xFFFFFF; int ecount = dis2.readInt(); int offset = dis2.readInt(); using (BinaryReader dis3 = new BinaryReader( new MemoryStream(manifestData, offset, ecount * 4))) { for (int j = 0; j < ecount; j++) { } } } } // logger.Debug("read table 2"); /** TABLE 2 - Manifest entries */ int entrySize = b.stride; for (int i = 0; i < count; i++) { int start = tableOffset + (i * entrySize); using (BinaryReader dis = new BinaryReader( new MemoryStream(manifestData, start, entrySize))) { ManifestEntry entry = new ManifestEntry(dis); manifestEntries.Add(entry); } } // logger.Debug("build cache"); Dictionary <string, List <int> > filenameEntryIndexDictT = new Dictionary <string, List <int> >(); Dictionary <string, List <int> > idEntryIndexDictT = new Dictionary <string, List <int> >(); for (int i = 0; i < manifestEntries.Count; i++) { ManifestEntry e = manifestEntries[i]; putFilenameCacheEntry(e, i, filenameEntryIndexDictT); putIDCacheEntry(e, i, idEntryIndexDictT); } foreach (string x in filenameEntryIndexDictT.Keys) { this.filenameEntryIndexDict.Add(x, filenameEntryIndexDictT[x].ToArray()); } foreach (string x in idEntryIndexDictT.Keys) { this.idEntryIndexDict.Add(x, idEntryIndexDictT[x].ToArray()); } }