Mercurial > repos > IBDev-IBBoard.WarFoundry.API
comparison API/AbstractWarFoundryLoader.cs @ 337:3c4a6403a88c
* Fix capitalisation so that new files are in the namespace
no-open-ticket
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 03 Apr 2011 18:50:32 +0000 |
parents | |
children | 71fceea2725b |
comparison
equal
deleted
inserted
replaced
336:3631c1493c7f | 337:3c4a6403a88c |
---|---|
1 // This file (AbstractWarFoundryLoader.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2009 IBBoard | |
2 // | |
3 // The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license. | |
4 | |
5 using System; | |
6 using System.Collections.Generic; | |
7 using System.IO; | |
8 using IBBoard.Collections; | |
9 using IBBoard.IO; | |
10 using IBBoard.Logging; | |
11 using IBBoard.WarFoundry.API.Factories; | |
12 using IBBoard.WarFoundry.API.Objects; | |
13 | |
14 namespace IBBoard.WarFoundry.API | |
15 { | |
16 /// <summary> | |
17 /// The base abstract implementation of a WarFoundry file loader | |
18 /// </summary> | |
19 public abstract class AbstractWarFoundryLoader | |
20 { | |
21 private ICollection<DirectoryInfo> directories; | |
22 private ICollection<INativeWarFoundryFactory> factories; | |
23 private ICollection<INonNativeWarFoundryFactory> nonNativeFactories; | |
24 private Dictionary<IWarFoundryFactory, SimpleSet<IWarFoundryObject>> loadedObjects; | |
25 | |
26 public delegate void FileLoadingCompleteDelegate(List<FileLoadFailure> failures); | |
27 | |
28 public event MethodInvoker FileLoadingStarted; | |
29 | |
30 public event FileLoadingCompleteDelegate FileLoadingFinished; | |
31 | |
32 protected AbstractWarFoundryLoader() | |
33 { | |
34 directories = new List<DirectoryInfo>(); | |
35 factories = new List<INativeWarFoundryFactory>(); | |
36 nonNativeFactories = new List<INonNativeWarFoundryFactory>(); | |
37 loadedObjects = new Dictionary<IWarFoundryFactory,SimpleSet<IWarFoundryObject>>(); | |
38 } | |
39 | |
40 /// <summary> | |
41 /// Adds a directory to the collection of directories that will be searched for WarFoundry data files. | |
42 /// </summary> | |
43 /// <param name="directory"> | |
44 /// The <see cref="DirectoryInfo"/> to add to the list for searching for data files | |
45 /// </param> | |
46 public void AddLoadDirectory(DirectoryInfo directory) | |
47 { | |
48 if (!directories.Contains(directory)) | |
49 { | |
50 directories.Add(directory); | |
51 } | |
52 } | |
53 | |
54 /// <summary> | |
55 /// Removes a directory from the collection of directories that will be searched for WarFoundry data files. | |
56 /// </summary> | |
57 /// <param name="directory"> | |
58 /// A <see cref="DirectoryInfo"/> | |
59 /// </param> | |
60 public void RemoveLoadDirectory(DirectoryInfo directory) | |
61 { | |
62 if (directories.Contains(directory)) | |
63 { | |
64 directories.Remove(directory); | |
65 } | |
66 } | |
67 | |
68 /// <summary> | |
69 /// Registers a <see cref="INativeWarFoundryFactory"/> as a factory that can parse native data files. | |
70 /// </summary> | |
71 /// <param name="factory"> | |
72 /// The <see cref="INativeWarFoundryFactory"/> to register to parse native data files. | |
73 /// </param> | |
74 public virtual void RegisterFactory(INativeWarFoundryFactory factory) | |
75 { | |
76 if (!factories.Contains(factory)) | |
77 { | |
78 factories.Add(factory); | |
79 } | |
80 } | |
81 | |
82 /// <summary> | |
83 /// Unregisters a <see cref="INativeWarFoundryFactory"/> so that it will no longer be used to try to parse native data files. | |
84 /// </summary> | |
85 /// <param name="factory"> | |
86 /// The <see cref="INativeWarFoundryFactory"/> to remove from the collection of factories that are used to try to parse native data files. | |
87 /// </param> | |
88 public virtual void UnregisterFactory(INativeWarFoundryFactory factory) | |
89 { | |
90 if (factories.Contains(factory)) | |
91 { | |
92 factories.Remove(factory); | |
93 } | |
94 } | |
95 | |
96 /// <summary> | |
97 /// Registers a <see cref="INonNativeWarFoundryFactory"/> so that it will be used to try to parse non-native data files from other applications. | |
98 /// </summary> | |
99 /// <param name="factory"> | |
100 /// The <see cref="INonNativeWarFoundryFactory"/> to register to parse non-native data files. | |
101 /// </param> | |
102 public virtual void RegisterNonNativeFactory(INonNativeWarFoundryFactory factory) | |
103 { | |
104 if (!nonNativeFactories.Contains(factory)) | |
105 { | |
106 nonNativeFactories.Add(factory); | |
107 } | |
108 } | |
109 | |
110 /// <summary> | |
111 /// Unregisters a <see cref="INonNativeWarFoundryFactory"/> so that it will no longer be used to try to parse non-native data files from other applications. | |
112 /// </summary> | |
113 /// <param name="factory"> | |
114 /// The <see cref="INonNativeWarFoundryFactory"/> to remove from the collection of factories that are used to try to parse non-native data files. | |
115 /// </param> | |
116 public virtual void UnregisterNonNativeFactory(INonNativeWarFoundryFactory factory) | |
117 { | |
118 if (nonNativeFactories.Contains(factory)) | |
119 { | |
120 nonNativeFactories.Remove(factory); | |
121 } | |
122 } | |
123 | |
124 /// <summary> | |
125 /// Loads all of the data files in the registered directories. | |
126 /// </summary> | |
127 /// <returns> | |
128 /// A <see cref="List"/> of <see cref="FileLoadFailure"/> for files that failed to load | |
129 /// </returns> | |
130 public List<FileLoadFailure> LoadFiles() | |
131 { | |
132 PrepareForFileLoad(); | |
133 Dictionary<FileInfo, IWarFoundryFactory> loadableRaces = new Dictionary<FileInfo, IWarFoundryFactory>(); | |
134 Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems = new Dictionary<FileInfo, IWarFoundryFactory>(); | |
135 List<FileLoadFailure> failedLoads = FillLoadableFiles(loadableRaces, loadableGameSystems); | |
136 failedLoads.AddRange(LoadGameSystems(loadableGameSystems)); | |
137 failedLoads.AddRange(LoadRaces(loadableRaces)); | |
138 OnFileLoadingFinished(failedLoads); | |
139 FinishFileLoad(); | |
140 return failedLoads; | |
141 } | |
142 | |
143 private void OnFileLoadingFinished(List<FileLoadFailure> failures) | |
144 { | |
145 if (FileLoadingFinished != null) | |
146 { | |
147 FileLoadingFinished(failures); | |
148 } | |
149 } | |
150 | |
151 protected virtual void PrepareForFileLoad() | |
152 { | |
153 //Do nothing special | |
154 } | |
155 | |
156 protected virtual void FinishFileLoad() | |
157 { | |
158 //Do nothing special | |
159 } | |
160 | |
161 private List<FileLoadFailure> FillLoadableFiles(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems) | |
162 { | |
163 List<FileLoadFailure> fails = new List<FileLoadFailure>(); | |
164 | |
165 foreach (DirectoryInfo directory in directories) | |
166 { | |
167 directory.Refresh(); | |
168 | |
169 if (directory.Exists) | |
170 { | |
171 List<FileLoadFailure> directoryFails = FillLoadableFilesForDirectory(loadableRaces, loadableGameSystems, directory); | |
172 fails.AddRange(directoryFails); | |
173 } | |
174 else | |
175 { | |
176 LogNotifier.WarnFormat(GetType(), "Load for {0} failed because directory didn't exist", directory.FullName); | |
177 } | |
178 } | |
179 | |
180 return fails; | |
181 } | |
182 | |
183 private List<FileLoadFailure> FillLoadableFilesForDirectory(Dictionary<FileInfo, IWarFoundryFactory> loadableRaces, Dictionary<FileInfo, IWarFoundryFactory> loadableGameSystems, DirectoryInfo directory) | |
184 { | |
185 List<FileLoadFailure> fails = new List<FileLoadFailure>(); | |
186 LogNotifier.Debug(GetType(), "Load from " + directory.FullName); | |
187 | |
188 foreach (FileInfo file in directory.GetFiles()) | |
189 { | |
190 IWarFoundryFactory factory = GetGameSystemLoadingFactoryForFile(file); | |
191 | |
192 if (factory != null) | |
193 { | |
194 loadableGameSystems.Add(file, factory); | |
195 } | |
196 else | |
197 { | |
198 factory = GetRaceLoadingFactoryForFile(file); | |
199 | |
200 if (factory != null) | |
201 { | |
202 loadableRaces.Add(file, factory); | |
203 } | |
204 else | |
205 { | |
206 FileLoadFailure failure = new FileLoadFailure(file, "File not handled as a Race or Game System definition: {0}", "FileNotHandled"); | |
207 fails.Add(failure); | |
208 LogNotifier.Info(GetType(), failure.Message); | |
209 } | |
210 } | |
211 } | |
212 | |
213 foreach (DirectoryInfo subdir in directory.GetDirectories()) | |
214 { | |
215 fails.AddRange(FillLoadableFilesForDirectory(loadableRaces, loadableGameSystems, subdir)); | |
216 } | |
217 | |
218 return fails; | |
219 } | |
220 | |
221 private IWarFoundryFactory GetGameSystemLoadingFactoryForFile(FileInfo file) | |
222 { | |
223 IWarFoundryFactory loadingFactory = null; | |
224 | |
225 foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) | |
226 { | |
227 if (factory.CanHandleFileAsGameSystem(file)) | |
228 { | |
229 loadingFactory = factory; | |
230 break; | |
231 } | |
232 } | |
233 | |
234 if (loadingFactory == null) | |
235 { | |
236 foreach (INativeWarFoundryFactory factory in factories) | |
237 { | |
238 if (factory.CanHandleFileAsGameSystem(file)) | |
239 { | |
240 loadingFactory = factory; | |
241 break; | |
242 } | |
243 } | |
244 } | |
245 | |
246 return loadingFactory; | |
247 } | |
248 | |
249 private IWarFoundryFactory GetRaceLoadingFactoryForFile(FileInfo file) | |
250 { | |
251 IWarFoundryFactory loadingFactory = null; | |
252 | |
253 foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) | |
254 { | |
255 if (factory.CanHandleFileAsRace(file)) | |
256 { | |
257 loadingFactory = factory; | |
258 break; | |
259 } | |
260 } | |
261 | |
262 if (loadingFactory == null) | |
263 { | |
264 foreach (INativeWarFoundryFactory factory in factories) | |
265 { | |
266 if (factory.CanHandleFileAsRace(file)) | |
267 { | |
268 loadingFactory = factory; | |
269 break; | |
270 } | |
271 } | |
272 } | |
273 | |
274 return loadingFactory; | |
275 } | |
276 | |
277 private List<FileLoadFailure> LoadGameSystems(Dictionary<FileInfo, IWarFoundryFactory> gameSystemFiles) | |
278 { | |
279 List<FileLoadFailure> fails = new List<FileLoadFailure>(); | |
280 | |
281 | |
282 foreach (FileInfo file in gameSystemFiles.Keys) | |
283 { | |
284 FileLoadFailure failure = null; | |
285 | |
286 try | |
287 { | |
288 bool loaded = LoadObject(file, gameSystemFiles[file]); | |
289 | |
290 if (!loaded) | |
291 { | |
292 failure = new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as GameSystem using {1}"); | |
293 } | |
294 } | |
295 catch (Exception ex) | |
296 { | |
297 failure = new FileLoadFailure(file, null, ex.Message, null, ex); | |
298 } | |
299 | |
300 if (failure != null) | |
301 { | |
302 fails.Add(failure); | |
303 LogNotifier.Warn(GetType(), failure.Message, failure.Exception); | |
304 } | |
305 } | |
306 | |
307 return fails; | |
308 } | |
309 | |
310 private List<FileLoadFailure> LoadRaces(Dictionary<FileInfo, IWarFoundryFactory> raceFiles) | |
311 { | |
312 List<FileLoadFailure> fails = new List<FileLoadFailure>(); | |
313 | |
314 foreach (FileInfo file in raceFiles.Keys) | |
315 { | |
316 FileLoadFailure failure = null; | |
317 | |
318 try | |
319 { | |
320 bool loaded = LoadObject(file, raceFiles[file]); | |
321 | |
322 if (!loaded) | |
323 { | |
324 failure = new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}"); | |
325 } | |
326 } | |
327 catch (Exception ex) | |
328 { | |
329 failure = new FileLoadFailure(file, null, ex.Message, null, ex); | |
330 } | |
331 | |
332 if (failure != null) | |
333 { | |
334 fails.Add(failure); | |
335 LogNotifier.Warn(GetType(), failure.Message, failure.Exception); | |
336 } | |
337 } | |
338 | |
339 return fails; | |
340 } | |
341 | |
342 private bool LoadObject(FileInfo file, IWarFoundryFactory factory) | |
343 { | |
344 LogNotifier.DebugFormat(GetType(), "Loading {0} using {1}", file.FullName, factory.GetType().Name); | |
345 factory.RaceLoaded+= StoreRace; | |
346 factory.GameSystemLoaded+= StoreGameSystem; | |
347 ICollection<IWarFoundryObject> objects = factory.CreateObjectsFromFile(file); | |
348 return objects.Count > 0; | |
349 } | |
350 | |
351 | |
352 /// <summary> | |
353 /// Loads a single file through the registered WarFoundryFactories, if a factory exists that supports the file format. | |
354 /// </summary> | |
355 /// <param name="file"> | |
356 /// A <see cref="FileInfo"/> for the file to attempt to load | |
357 /// </param> | |
358 /// <returns> | |
359 /// An ICollection of IWarFoundryObjects loaded from <code>file</code> | |
360 /// </returns> | |
361 public ICollection<IWarFoundryObject> LoadFile(FileInfo file) | |
362 { | |
363 ICollection<IWarFoundryObject> objs = null; | |
364 IWarFoundryFactory loadFactory = null; | |
365 | |
366 try | |
367 { | |
368 objs = LoadFileWithNonNativeFactories(file, out loadFactory); | |
369 | |
370 if (objs == null) | |
371 { | |
372 objs = LoadFileWithNativeFactories(file, out loadFactory); | |
373 } | |
374 } | |
375 catch (InvalidFileException ex) | |
376 { | |
377 LogNotifier.Error(GetType(), file.FullName + " failed to load", ex); | |
378 } | |
379 | |
380 if (objs != null) | |
381 { | |
382 AddLoadedObjects(objs, loadFactory); | |
383 } | |
384 else | |
385 { | |
386 objs = new List<IWarFoundryObject>(); | |
387 } | |
388 | |
389 return objs; | |
390 } | |
391 | |
392 private ICollection<IWarFoundryObject> LoadFileWithNonNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory) | |
393 { | |
394 ICollection<IWarFoundryObject> objs = null; | |
395 loadFactory = null; | |
396 | |
397 if (nonNativeFactories.Count > 0) | |
398 { | |
399 LogNotifier.Debug(GetType(), "Attempting to load " + file.FullName + " as a non-native file"); | |
400 | |
401 foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) | |
402 { | |
403 bool canLoad = factory.CanHandleFileFormat(file); | |
404 LogNotifier.Debug(GetType(), "Load using " + factory.GetType().FullName + "? " + (canLoad ? "yes" : "no")); | |
405 | |
406 if (canLoad) | |
407 { | |
408 objs = factory.CreateObjectsFromFile(file); | |
409 | |
410 if (objs != null) | |
411 { | |
412 loadFactory = factory; | |
413 break; | |
414 } | |
415 } | |
416 } | |
417 } | |
418 | |
419 return objs; | |
420 } | |
421 | |
422 private ICollection<IWarFoundryObject> LoadFileWithNativeFactories(FileInfo file, out IWarFoundryFactory loadFactory) | |
423 { | |
424 ICollection<IWarFoundryObject> objs = null; | |
425 loadFactory = null; | |
426 | |
427 if (factories.Count > 0) | |
428 { | |
429 LogNotifier.Debug(GetType(), "Attempting to load " + file.FullName + " as native file"); | |
430 | |
431 foreach (INativeWarFoundryFactory factory in factories) | |
432 { | |
433 if (factory.CanHandleFileFormat(file)) | |
434 { | |
435 objs = factory.CreateObjectsFromFile(file); | |
436 | |
437 if (objs != null) | |
438 { | |
439 loadFactory = factory; | |
440 break; | |
441 } | |
442 } | |
443 } | |
444 } | |
445 | |
446 return objs; | |
447 } | |
448 | |
449 private void AddLoadedObjects(ICollection<IWarFoundryObject> loadedObjs, IWarFoundryFactory factory) | |
450 { | |
451 SimpleSet<IWarFoundryObject> objs; | |
452 loadedObjects.TryGetValue(factory, out objs); | |
453 | |
454 if (objs == null) | |
455 { | |
456 objs = new SimpleSet<IWarFoundryObject>(); | |
457 loadedObjects.Add(factory, objs); | |
458 } | |
459 | |
460 objs.AddRange(loadedObjs); | |
461 StoreObjects(loadedObjs); | |
462 } | |
463 | |
464 private void StoreObjects(ICollection<IWarFoundryObject> loadedObjects) | |
465 { | |
466 foreach (IWarFoundryObject loadedObject in loadedObjects) | |
467 { | |
468 if (loadedObject is GameSystem) | |
469 { | |
470 StoreGameSystem((GameSystem)loadedObject); | |
471 } | |
472 else if (loadedObject is Race) | |
473 { | |
474 StoreRace((Race)loadedObject); | |
475 } | |
476 } | |
477 } | |
478 | |
479 protected void StoreGameSystem(GameSystem system) | |
480 { | |
481 GameSystem existingSystem = GetExistingSystemForSystem(system); | |
482 | |
483 if (existingSystem != null) | |
484 { | |
485 if (!system.Equals(existingSystem)) | |
486 { | |
487 //TODO: Raise an event to say we got a different duplicate | |
488 //We can't just fail, because failing is for completely unhandled files, not for objects in a file | |
489 } | |
490 } | |
491 else | |
492 { | |
493 DoStoreGameSystem(system); | |
494 } | |
495 } | |
496 | |
497 /// <summary> | |
498 /// Gets a game system that has already been loaded that duplicates the supplied game system's ID, if one exists. | |
499 /// </summary> | |
500 /// <param name="system"> | |
501 /// The <see cref="GameSystem"/> to find pre-existing duplicates of | |
502 /// </param> | |
503 /// <returns> | |
504 /// <code>null</code> if no existing duplicate exists, else the duplicate <see cref="GameSystem"/> | |
505 /// </returns> | |
506 protected abstract GameSystem GetExistingSystemForSystem(GameSystem system); | |
507 | |
508 /// <summary> | |
509 /// Stores a GameSystem in the loader's relevant storage structure | |
510 /// </summary> | |
511 /// <param name="system"> | |
512 /// The loaded <see cref="GameSystem"/> to store | |
513 /// </param> | |
514 protected abstract void DoStoreGameSystem(GameSystem system); | |
515 | |
516 protected void StoreRace(Race race) | |
517 { | |
518 if (race.GameSystem == null) | |
519 { | |
520 throw new InvalidOperationException("Race cannot have null game system. Game system should be loaded before race."); | |
521 } | |
522 | |
523 DoStoreRace(race); | |
524 } | |
525 | |
526 /// <summary> | |
527 /// Performs the implementation specific storage of a race | |
528 /// </summary> | |
529 /// <param name="race"> | |
530 /// The <see cref="Race"/> to store | |
531 /// </param> | |
532 protected abstract void DoStoreRace(Race race); | |
533 | |
534 /// <summary> | |
535 /// Gets all <see cref="GameSystem"/>s that are currently available, determined by those that can be loaded with the current <see cref="IWarFoundryFactory"/>s. | |
536 /// </summary> | |
537 /// <returns> | |
538 /// An array of <see cref="GameSystem"/>s that are currently available. | |
539 /// </returns> | |
540 public abstract GameSystem[] GetGameSystems(); | |
541 | |
542 /// <summary> | |
543 /// Gets a single <see cref="GameSystem"/> with a given ID. | |
544 /// </summary> | |
545 /// <param name="systemID"> | |
546 /// The ID of the <see cref="GameSystem"/> to get, as a <see cref="System.String"/>. | |
547 /// </param> | |
548 /// <returns> | |
549 /// The <see cref="GameSystem"/> with the given ID, or <code>null</code> if one doesn't exist. | |
550 /// </returns> | |
551 public abstract GameSystem GetGameSystem(string systemID); | |
552 | |
553 /// <summary> | |
554 /// Removes a loaded <see cref="GameSystem"/>. Used when a GameSystem fails to complete loading | |
555 /// </summary> | |
556 /// <param name="system">The GameSystem to remove</param> | |
557 protected internal abstract void RemoveGameSystem(GameSystem system); | |
558 | |
559 /// <summary> | |
560 /// Gets an array of the races for the specified <see cref="GameSystem"/>. | |
561 /// </summary> | |
562 /// <param name="system"> | |
563 /// The <see cref="GameSystem"/> to get the available races for. | |
564 /// </param> | |
565 /// <returns> | |
566 /// An array of <see cref="Race"/>s for the <see cref="GameSystem"/> | |
567 /// </returns> | |
568 public abstract Race[] GetRaces(GameSystem system); | |
569 | |
570 /// <summary> | |
571 /// Gets a single race for a given <see cref="GameSystem"/> by ID of the race. | |
572 /// </summary> | |
573 /// <param name="system"> | |
574 /// The <see cref="GameSystem"/> that the race is part of. | |
575 /// </param> | |
576 /// <param name="raceID"> | |
577 /// A <see cref="System.String"/> ID for the race to load. | |
578 /// </param> | |
579 /// <returns> | |
580 /// A <see cref="Race"/> with the specified ID from the <see cref="GameSystem"/>, or <code>null</code> if one doesn't exist. | |
581 /// </returns> | |
582 public abstract Race GetRace(GameSystem system, string raceID); | |
583 | |
584 /// <summary> | |
585 /// Gets a single race for a given <see cref="GameSystem"/> by the race's ID and sub-race ID. | |
586 /// </summary> | |
587 /// <param name="system"> | |
588 /// The <see cref="GameSystem"/> that the race is part of. | |
589 /// </param> | |
590 /// <param name="raceID"> | |
591 /// The <see cref="System.String"/> ID for the race to load. | |
592 /// </param> | |
593 /// <param name="raceSubID"> | |
594 /// A <see cref="System.String"/> | |
595 /// </param> | |
596 /// <returns> | |
597 /// A <see cref="Race"/> | |
598 /// </returns> | |
599 public abstract Race GetRace(GameSystem system, string raceID, string raceSubID); | |
600 | |
601 protected internal abstract void RemoveRace(Race race); | |
602 | |
603 /// <summary> | |
604 /// Gets the IDs of all of the game systems currently available. | |
605 /// </summary> | |
606 /// <returns> | |
607 /// An array of <see cref="System.String"/>s representing the IDs of the game systems. | |
608 /// </returns> | |
609 public virtual string[] GetGameSystemIDs() | |
610 { | |
611 GameSystem[] systems = GetGameSystems(); | |
612 return GetWarFoundryObjectIDs(systems); | |
613 } | |
614 | |
615 protected string[] GetWarFoundryObjectIDs(WarFoundryObject[] objs) | |
616 { | |
617 int objCount = objs.Length; | |
618 string[] keys = new string[objCount]; | |
619 | |
620 for (int i = 0; i < objCount; i++) | |
621 { | |
622 keys[i] = objs[i].ID; | |
623 } | |
624 | |
625 return keys; | |
626 } | |
627 | |
628 /// <summary> | |
629 /// Gets the IDs of all of the races of a specified game system. | |
630 /// </summary> | |
631 /// <param name="system"> | |
632 /// The <see cref="GameSystem"/> to get the available races for. | |
633 /// </param> | |
634 /// <returns> | |
635 /// An array of <see cref="System.String"/>s representing the IDs of the races of the specified game system. | |
636 /// </returns> | |
637 public virtual string[] GetSystemRaceIDs(GameSystem system) | |
638 { | |
639 Race[] races = GetRaces(system); | |
640 return GetWarFoundryObjectIDs(races); | |
641 } | |
642 | |
643 public Army LoadArmy(FileInfo file) | |
644 { | |
645 IWarFoundryFactory factory = GetArmyLoadingFactoryForFile(file); | |
646 Army loadedArmy = null; | |
647 | |
648 if (factory != null) | |
649 { | |
650 ICollection<IWarFoundryObject> objs = factory.CreateObjectsFromFile(file); | |
651 | |
652 if (objs.Count == 1) | |
653 { | |
654 foreach (IWarFoundryObject systemCount in objs) | |
655 { | |
656 if (systemCount is Army) | |
657 { | |
658 loadedArmy = (Army)systemCount; | |
659 } | |
660 } | |
661 } | |
662 } | |
663 | |
664 return loadedArmy; | |
665 } | |
666 | |
667 private IWarFoundryFactory GetArmyLoadingFactoryForFile(FileInfo file) | |
668 { | |
669 IWarFoundryFactory loadingFactory = null; | |
670 | |
671 foreach (INonNativeWarFoundryFactory factory in nonNativeFactories) | |
672 { | |
673 if (factory.CanHandleFileAsArmy(file)) | |
674 { | |
675 loadingFactory = factory; | |
676 break; | |
677 } | |
678 } | |
679 | |
680 if (loadingFactory == null) | |
681 { | |
682 foreach (INativeWarFoundryFactory factory in factories) | |
683 { | |
684 if (factory.CanHandleFileAsArmy(file)) | |
685 { | |
686 loadingFactory = factory; | |
687 break; | |
688 } | |
689 } | |
690 } | |
691 | |
692 return loadingFactory; | |
693 } | |
694 } | |
695 } |