22using PG . StarWarsGame . Engine . ErrorReporting ;
33using PG . StarWarsGame . Engine . IO . Repositories ;
44using PG . StarWarsGame . Engine . Xml ;
5+ using PG . StarWarsGame . Engine . Xml . Parsers ;
56using System ;
7+ using System . Collections . Generic ;
8+ using System . Collections . ObjectModel ;
69using System . Linq ;
710using System . Threading ;
811using System . Threading . Tasks ;
912
1013namespace PG . StarWarsGame . Engine . GameObjects ;
1114
12- internal class GameObjectTypeGameManager ( GameRepository repository , GameEngineErrorReporterWrapper errorReporter , IServiceProvider serviceProvider )
13- : GameManagerBase < GameObject > ( repository , errorReporter , serviceProvider ) , IGameObjectTypeGameManager
15+ internal class GameObjectTypeGameManager : GameManagerBase < GameObject > , IGameObjectTypeGameManager
1416{
17+ private readonly List < GameObject > _gameObjects ;
18+
19+ public GameObjectTypeGameManager (
20+ GameRepository repository ,
21+ GameEngineErrorReporterWrapper errorReporter ,
22+ IServiceProvider serviceProvider )
23+ : base ( repository , errorReporter , serviceProvider )
24+ {
25+ _gameObjects = new List < GameObject > ( ) ;
26+ GameObjects = new ReadOnlyCollection < GameObject > ( _gameObjects ) ;
27+ }
28+
29+
30+ public IReadOnlyList < GameObject > GameObjects
31+ {
32+ get
33+ {
34+ ThrowIfNotInitialized ( ) ;
35+ return field ;
36+ }
37+ }
38+
1539 protected override async Task InitializeCoreAsync ( CancellationToken token )
1640 {
1741 Logger ? . LogInformation ( "Parsing GameObjects..." ) ;
1842 await Task . Run ( ParseGameObjectDatabases , token ) ;
1943 }
2044
21-
2245 private void ParseGameObjectDatabases ( )
2346 {
24- var parser = new PetroglyphStarWarsGameXmlParser ( GameRepository ,
47+ var gameParser = new PetroglyphStarWarsGameXmlParser ( GameRepository ,
2548 new PetroglyphStarWarsGameXmlParseSettings
2649 {
2750 GameManager = ToString ( ) ,
2851 InvalidFilesListXmlFailsInitialization = true ,
2952 InvalidObjectXmlFailsInitialization = false ,
3053 } , ServiceProvider , ErrorReporter ) ;
3154
32- var xmlFileList = parser . ParseFileList ( @"DATA\XML\GAMEOBJECTFILES.XML" ) . Files
33- . Select ( x =>
34- {
35- var filePath = FileSystem . Path . Combine ( @".\DATA\XML\" , x ) ;
36- VerifyFilePathLength ( filePath ) ;
37- return filePath ;
38- } ) . ToList ( ) ;
39-
55+ var xmlFileList = gameParser . ParseFileList ( @"DATA\XML\GAMEOBJECTFILES.XML" ) . Files
56+ . Select ( x => FileSystem . Path . Combine ( @".\DATA\XML\" , x ) )
57+ . Where ( VerifyFilePathLength )
58+ . ToList ( ) ;
4059
41- // var gameObjectFileParser = new GameObjectFileParser(serviceProvider, errorReporter );
60+ var gameObjectFileParser = new GameObjectFileParser ( ServiceProvider , ErrorReporter ) ;
4261
4362 var allLoaded = false ;
63+
64+ // This also acts a guard against infinite loops in case of unexpected circular dependencies or
65+ // when a unit declares itself as its own <Variant_Of_Existing_Type>
4466 for ( var passNumber = 0 ; ! allLoaded && passNumber < 10 ; passNumber ++ )
4567 {
68+ Logger ? . LogDebug ( "***** Parsing game object types - pass {PassNumber} *****" , passNumber ) ;
69+
70+ if ( passNumber != 0 )
71+ gameObjectFileParser . OverlayLoad = true ;
72+
4673 foreach ( var gameObjectXmlFile in xmlFileList )
4774 {
4875 if ( passNumber == 0 )
4976 {
50- //ParseSingleGameObjectFile(gameObjectXmlFile, parser, gameObjectFileParser);
77+ try
78+ {
79+ gameObjectFileParser . GameObjectParsed += OnGameObjectParsed ;
80+ ParseSingleGameObjectFile ( gameObjectXmlFile , gameParser , gameObjectFileParser ) ;
81+ }
82+ finally
83+ {
84+ gameObjectFileParser . GameObjectParsed -= OnGameObjectParsed ;
85+ }
5186 }
5287 else
5388 {
89+ foreach ( var gameObject in _gameObjects )
90+ {
91+ if ( ! gameObject . IsLoadingComplete && gameObject . Location . XmlFile == gameObjectXmlFile )
92+ ParseSingleGameObjectFile ( gameObjectXmlFile , gameParser , gameObjectFileParser ) ;
93+ }
5494 }
5595 }
5696
@@ -65,12 +105,38 @@ private void ParseGameObjectDatabases()
65105 }
66106 }
67107
68- //private void ParseSingleGameObjectFile(string file, EngineXmlParser engineParser, GameObjectFileParser gameObjectFileParser)
69- //{
70- // engineParser.ParseEntriesFromContainerFile(gameObjectFileParser, file, NamedEntries);
71- //}
108+ private void OnGameObjectParsed ( object sender , GameObjectParsedEventArgs e )
109+ {
110+ if ( ! e . Unique )
111+ {
112+ var entries = NamedEntries . GetValues ( e . ParsedElement . Crc32 )
113+ . Select ( x => x . Name ) ;
114+ ErrorReporter . Assert ( EngineAssert . Create (
115+ EngineAssertKind . DuplicateEntry ,
116+ e . ParsedElement . Crc32 , entries ,
117+ $ "Error: Game object type { e . ParsedElement . Name } is defined multiple times.") ) ;
118+ }
72119
73- private void VerifyFilePathLength ( string filePath )
120+ if ( NamedEntries . ValueCount >= 0x10000 )
121+ {
122+ ErrorReporter . Assert (
123+ EngineAssert . Create (
124+ EngineAssertKind . ValueOutOfRange ,
125+ NamedEntries . ValueCount ,
126+ [ ToString ( ) ] ,
127+ "Too many game object types defined." ) ) ;
128+ }
129+ }
130+
131+ private void ParseSingleGameObjectFile (
132+ string file ,
133+ PetroglyphStarWarsGameXmlParser gameParser ,
134+ GameObjectFileParser gameObjectFileParser )
135+ {
136+ gameParser . ParseObjectsFromContainerFile ( file , gameObjectFileParser , NamedEntries ) ;
137+ }
138+
139+ private bool VerifyFilePathLength ( string filePath )
74140 {
75141 if ( filePath . Length > PGConstants . MaxGameObjectDatabaseFileName )
76142 {
@@ -81,6 +147,9 @@ private void VerifyFilePathLength(string filePath)
81147 GameManager = ToString ( ) ,
82148 Message = $ "Game object file '{ filePath } ' is longer than { PGConstants . MaxGameObjectDatabaseFileName } characters."
83149 } ) ;
150+ return false ;
84151 }
152+
153+ return true ;
85154 }
86155}
0 commit comments