1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
using System.IO; |
4 |
using Oni.Collections; |
5 |
|
6 |
namespace Oni |
7 |
{ |
8 |
internal sealed class InstanceFileManager |
9 |
{ |
10 |
private readonly List<string> searchPaths = new List<string>(); |
11 |
private readonly Dictionary<string, InstanceFile> loadedFiles = new Dictionary<string, InstanceFile>(StringComparer.OrdinalIgnoreCase); |
12 |
private Dictionary<string, string> files; |
13 |
|
14 |
public InstanceFile OpenFile(string filePath) |
15 |
{ |
16 |
InstanceFile file; |
17 |
|
18 |
if (!loadedFiles.TryGetValue(filePath, out file)) |
19 |
{ |
20 |
try |
21 |
{ |
22 |
file = InstanceFile.Read(this, filePath); |
23 |
} |
24 |
catch (Exception ex) |
25 |
{ |
26 |
Console.Error.WriteLine("Error opening file {0}: {1}", filePath, ex.Message); |
27 |
throw; |
28 |
} |
29 |
|
30 |
loadedFiles.Add(filePath, file); |
31 |
} |
32 |
|
33 |
return file; |
34 |
} |
35 |
|
36 |
public List<InstanceFile> OpenDirectories(string[] dirPaths) |
37 |
{ |
38 |
var files = new List<InstanceFile>(); |
39 |
var seenFileNames = new Set<string>(StringComparer.Ordinal); |
40 |
|
41 |
Array.Reverse(dirPaths); |
42 |
|
43 |
foreach (string dirPath in dirPaths) |
44 |
{ |
45 |
var filePaths = FindFiles(dirPath); |
46 |
|
47 |
foreach (string filePath in filePaths) |
48 |
{ |
49 |
if (!seenFileNames.Contains(Path.GetFileName(filePath))) |
50 |
files.Add(OpenFile(filePath)); |
51 |
} |
52 |
|
53 |
foreach (string filePath in filePaths) |
54 |
seenFileNames.Add(Path.GetFileName(filePath)); |
55 |
} |
56 |
|
57 |
return files; |
58 |
} |
59 |
|
60 |
public List<InstanceFile> OpenDirectory(string dirPath) |
61 |
{ |
62 |
var files = new List<InstanceFile>(); |
63 |
|
64 |
foreach (string filePath in FindFiles(dirPath)) |
65 |
files.Add(OpenFile(filePath)); |
66 |
|
67 |
return files; |
68 |
} |
69 |
|
70 |
public void AddSearchPath(string path) |
71 |
{ |
72 |
if (Directory.Exists(path)) |
73 |
searchPaths.Add(path); |
74 |
} |
75 |
|
76 |
public InstanceFile FindInstance(string instanceName) |
77 |
{ |
78 |
if (files == null) |
79 |
{ |
80 |
files = new Dictionary<string, string>(StringComparer.Ordinal); |
81 |
|
82 |
foreach (string searchPath in searchPaths) |
83 |
{ |
84 |
foreach (string filePath in FindFiles(searchPath)) |
85 |
{ |
86 |
string name = Importer.DecodeFileName(filePath); |
87 |
|
88 |
if (!files.ContainsKey(name)) |
89 |
files[name] = filePath; |
90 |
} |
91 |
} |
92 |
} |
93 |
|
94 |
string instanceFilePath; |
95 |
|
96 |
if (!files.TryGetValue(instanceName, out instanceFilePath)) |
97 |
return null; |
98 |
|
99 |
var file = OpenFile(instanceFilePath); |
100 |
|
101 |
if (file == null) |
102 |
return null; |
103 |
|
104 |
var descriptor = file.Descriptors[0]; |
105 |
|
106 |
if (file.Header.Version != InstanceFileHeader.Version32) |
107 |
return null; |
108 |
|
109 |
if (descriptor == null || !descriptor.HasName || descriptor.FullName != instanceName) |
110 |
return null; |
111 |
|
112 |
return file; |
113 |
} |
114 |
|
115 |
public InstanceFile FindInstance(string instanceName, InstanceFile baseFile) |
116 |
{ |
117 |
if (files == null) |
118 |
{ |
119 |
files = new Dictionary<string, string>(StringComparer.Ordinal); |
120 |
|
121 |
foreach (string filePath in FindFiles(Path.GetDirectoryName(baseFile.FilePath))) |
122 |
files[Importer.DecodeFileName(filePath)] = filePath; |
123 |
|
124 |
foreach (string searchPath in searchPaths) |
125 |
{ |
126 |
foreach (string filePath in FindFiles(searchPath)) |
127 |
{ |
128 |
string name = Importer.DecodeFileName(filePath); |
129 |
|
130 |
if (!files.ContainsKey(name)) |
131 |
files[name] = filePath; |
132 |
} |
133 |
} |
134 |
} |
135 |
|
136 |
string instanceFilePath; |
137 |
|
138 |
if (!files.TryGetValue(instanceName, out instanceFilePath)) |
139 |
{ |
140 |
if (instanceName.Length > 4) |
141 |
instanceName = instanceName.Substring(4); |
142 |
|
143 |
if (!files.TryGetValue(instanceName, out instanceFilePath)) |
144 |
{ |
145 |
string level0FilePath = Path.Combine(Path.GetDirectoryName(baseFile.FilePath), "level0_Final.dat"); |
146 |
|
147 |
if (!File.Exists(level0FilePath)) |
148 |
return null; |
149 |
|
150 |
return OpenFile(level0FilePath); |
151 |
} |
152 |
} |
153 |
|
154 |
var file = OpenFile(instanceFilePath); |
155 |
|
156 |
if (file == null || file == baseFile) |
157 |
return null; |
158 |
|
159 |
var descriptor = file.Descriptors[0]; |
160 |
|
161 |
if (file.Header.Version == InstanceFileHeader.Version32) |
162 |
return file; |
163 |
|
164 |
if (descriptor == null || !descriptor.HasName || descriptor.FullName != instanceName) |
165 |
return null; |
166 |
|
167 |
return file; |
168 |
} |
169 |
|
170 |
private static List<string> FindFiles(string dirPath) |
171 |
{ |
172 |
var files = new List<string>(); |
173 |
|
174 |
if (Directory.Exists(dirPath)) |
175 |
FindFilesRecursive(dirPath, files); |
176 |
|
177 |
return files; |
178 |
} |
179 |
|
180 |
private static void FindFilesRecursive(string dirPath, List<string> files) |
181 |
{ |
182 |
files.AddRange(Directory.GetFiles(dirPath, "*.oni")); |
183 |
|
184 |
foreach (string childDirPath in Directory.GetDirectories(dirPath)) |
185 |
{ |
186 |
string name = Path.GetFileName(childDirPath); |
187 |
|
188 |
if (!string.Equals(name, "_noimport", StringComparison.OrdinalIgnoreCase) |
189 |
&& !string.Equals(name, "noimport", StringComparison.OrdinalIgnoreCase)) |
190 |
{ |
191 |
FindFilesRecursive(childDirPath, files); |
192 |
} |
193 |
} |
194 |
} |
195 |
} |
196 |
} |