using System; using System.Collections.Generic; using System.IO; using Oni.Collections; namespace Oni { internal sealed class InstanceFileManager { private readonly List searchPaths = new List(); private readonly Dictionary loadedFiles = new Dictionary(StringComparer.OrdinalIgnoreCase); private Dictionary files; public InstanceFile OpenFile(string filePath) { InstanceFile file; if (!loadedFiles.TryGetValue(filePath, out file)) { try { file = InstanceFile.Read(this, filePath); } catch (Exception ex) { Console.Error.WriteLine("Error opening file {0}: {1}", filePath, ex.Message); throw; } loadedFiles.Add(filePath, file); } return file; } public List OpenDirectories(string[] dirPaths) { var files = new List(); var seenFileNames = new Set(StringComparer.Ordinal); Array.Reverse(dirPaths); foreach (string dirPath in dirPaths) { var filePaths = FindFiles(dirPath); foreach (string filePath in filePaths) { if (!seenFileNames.Contains(Path.GetFileName(filePath))) files.Add(OpenFile(filePath)); } foreach (string filePath in filePaths) seenFileNames.Add(Path.GetFileName(filePath)); } return files; } public List OpenDirectory(string dirPath) { var files = new List(); foreach (string filePath in FindFiles(dirPath)) files.Add(OpenFile(filePath)); return files; } public void AddSearchPath(string path) { if (Directory.Exists(path)) searchPaths.Add(path); } public InstanceFile FindInstance(string instanceName) { if (files == null) { files = new Dictionary(StringComparer.Ordinal); foreach (string searchPath in searchPaths) { foreach (string filePath in FindFiles(searchPath)) { string name = Importer.DecodeFileName(filePath); if (!files.ContainsKey(name)) files[name] = filePath; } } } string instanceFilePath; if (!files.TryGetValue(instanceName, out instanceFilePath)) return null; var file = OpenFile(instanceFilePath); if (file == null) return null; var descriptor = file.Descriptors[0]; if (file.Header.Version != InstanceFileHeader.Version32) return null; if (descriptor == null || !descriptor.HasName || descriptor.FullName != instanceName) return null; return file; } public InstanceFile FindInstance(string instanceName, InstanceFile baseFile) { if (files == null) { files = new Dictionary(StringComparer.Ordinal); foreach (string filePath in FindFiles(Path.GetDirectoryName(baseFile.FilePath))) files[Importer.DecodeFileName(filePath)] = filePath; foreach (string searchPath in searchPaths) { foreach (string filePath in FindFiles(searchPath)) { string name = Importer.DecodeFileName(filePath); if (!files.ContainsKey(name)) files[name] = filePath; } } } string instanceFilePath; if (!files.TryGetValue(instanceName, out instanceFilePath)) { if (instanceName.Length > 4) instanceName = instanceName.Substring(4); if (!files.TryGetValue(instanceName, out instanceFilePath)) { string level0FilePath = Path.Combine(Path.GetDirectoryName(baseFile.FilePath), "level0_Final.dat"); if (!File.Exists(level0FilePath)) return null; return OpenFile(level0FilePath); } } var file = OpenFile(instanceFilePath); if (file == null || file == baseFile) return null; var descriptor = file.Descriptors[0]; if (file.Header.Version == InstanceFileHeader.Version32) return file; if (descriptor == null || !descriptor.HasName || descriptor.FullName != instanceName) return null; return file; } private static List FindFiles(string dirPath) { var files = new List(); if (Directory.Exists(dirPath)) FindFilesRecursive(dirPath, files); return files; } private static void FindFilesRecursive(string dirPath, List files) { files.AddRange(Directory.GetFiles(dirPath, "*.oni")); foreach (string childDirPath in Directory.GetDirectories(dirPath)) { string name = Path.GetFileName(childDirPath); if (!string.Equals(name, "_noimport", StringComparison.OrdinalIgnoreCase) && !string.Equals(name, "noimport", StringComparison.OrdinalIgnoreCase)) { FindFilesRecursive(childDirPath, files); } } } } }