bool IPackageLoader.TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package) { if (!filename.EndsWith(".bag", StringComparison.InvariantCultureIgnoreCase)) { package = null; return(false); } // A bag file is always accompanied with an .idx counterpart // For example: audio.bag requires the audio.idx file var indexFilename = Path.ChangeExtension(filename, ".idx"); List <IdxEntry> entries = null; try { // Build the index and dispose the stream, it is no longer needed after this using (var indexStream = context.Open(indexFilename)) entries = new IdxReader(indexStream).Entries; } catch { package = null; return(false); } package = new BagFile(s, entries, filename); return(true); }
public ObjectCreator(Manifest manifest, FileSystem.FileSystem modFiles) { typeCache = new Cache <string, Type>(FindType); ctorCache = new Cache <Type, ConstructorInfo>(GetCtor); // Allow mods to load types from the core Game assembly, and any additional assemblies they specify. var assemblyList = new List <Assembly>() { typeof(Game).Assembly }; foreach (var path in manifest.Assemblies) { var data = modFiles.Open(path).ReadAllBytes(); // .NET doesn't provide any way of querying the metadata of an assembly without either: // (a) loading duplicate data into the application domain, breaking the world. // (b) crashing if the assembly has already been loaded. // We can't check the internal name of the assembly, so we'll work off the data instead var hash = CryptoUtil.SHA1Hash(data); Assembly assembly; if (!ResolvedAssemblies.TryGetValue(hash, out assembly)) { assembly = Assembly.Load(data); ResolvedAssemblies.Add(hash, assembly); } assemblyList.Add(assembly); } AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; assemblies = assemblyList.SelectMany(asm => asm.GetNamespaces().Select(ns => Pair.New(asm, ns))).ToArray(); AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssembly; }
public bool TryParsePackage(Stream s, string filename, OpenRA.FileSystem.FileSystem context, out IReadOnlyPackage package) { if (!filename.EndsWith("DDF")) { package = null; return(false); } package = new DdfPackage(s, context.Open(filename.Replace(".DDF", ".ANI")), filename); return(true); }
Dictionary <string, PackageEntry> ParseIndex(Dictionary <uint, PackageEntry> entries) { var classicIndex = new Dictionary <string, PackageEntry>(); var crcIndex = new Dictionary <string, PackageEntry>(); var allPossibleFilenames = new HashSet <string>(); // Try and find a local mix database var dbNameClassic = PackageEntry.HashFilename("local mix database.dat", PackageHashType.Classic); var dbNameCRC = PackageEntry.HashFilename("local mix database.dat", PackageHashType.CRC32); foreach (var kv in entries) { if (kv.Key == dbNameClassic || kv.Key == dbNameCRC) { var db = new XccLocalDatabase(GetContent(kv.Value)); foreach (var e in db.Entries) { allPossibleFilenames.Add(e); } break; } } // Load the global mix database // TODO: This should be passed to the mix file ctor if (context.Exists("global mix database.dat")) { using (var db = new XccGlobalDatabase(context.Open("global mix database.dat"))) { foreach (var e in db.Entries) { allPossibleFilenames.Add(e); } } } foreach (var filename in allPossibleFilenames) { var classicHash = PackageEntry.HashFilename(filename, PackageHashType.Classic); var crcHash = PackageEntry.HashFilename(filename, PackageHashType.CRC32); PackageEntry e; if (entries.TryGetValue(classicHash, out e)) { classicIndex.Add(filename, e); } if (entries.TryGetValue(crcHash, out e)) { crcIndex.Add(filename, e); } } var bestIndex = crcIndex.Count > classicIndex.Count ? crcIndex : classicIndex; var unknown = entries.Count - bestIndex.Count; if (unknown > 0) { Log.Write("debug", "{0}: failed to resolve filenames for {1} unknown hashes".F(Name, unknown)); } return(bestIndex); }