88using TheEngine . PhysicsSystem ;
99using WDE . Common . DBC ;
1010using WDE . Common . MPQ ;
11+ using WDE . Common . Services . MessageBox ;
1112using WDE . MapRenderer . Managers ;
13+ using WDE . Module . Attributes ;
1214using WDE . MpqReader ;
1315using WDE . MpqReader . Structures ;
1416
1517namespace WDE . MapRenderer
1618{
19+ [ AutoRegister ]
1720 public class GameManager : IGame , IGameContext
1821 {
19- private IMpqArchive mpq ;
22+ private readonly IMpqService mpqService ;
2023 private readonly IGameView gameView ;
24+ private readonly IMessageBoxService messageBoxService ;
2125 private readonly IDatabaseClientFileOpener databaseClientFileOpener ;
2226 private AsyncMonitor monitor = new AsyncMonitor ( ) ;
2327 private Engine engine ;
2428 public event Action ? OnInitialized ;
29+ public event Action ? OnFailedInitialize ;
2530
26- public GameManager ( IMpqArchive mpq , IGameView gameView , IDatabaseClientFileOpener databaseClientFileOpener )
31+ public GameManager ( IMpqService mpqService ,
32+ IGameView gameView ,
33+ IMessageBoxService messageBoxService ,
34+ IDatabaseClientFileOpener databaseClientFileOpener )
2735 {
28- this . mpq = mpq ;
36+ this . mpqService = mpqService ;
2937 this . gameView = gameView ;
38+ this . messageBoxService = messageBoxService ;
3039 this . databaseClientFileOpener = databaseClientFileOpener ;
3140 UpdateLoop = new UpdateManager ( this ) ;
3241 }
3342
34- public void Initialize ( Engine engine )
43+ private bool TryOpenMpq ( out IMpqArchive m )
44+ {
45+ try
46+ {
47+ m = mpqService . Open ( ) ;
48+ return true ;
49+ }
50+ catch ( Exception e )
51+ {
52+ messageBoxService . ShowDialog ( new MessageBoxFactory < bool > ( )
53+ . SetTitle ( "Invalid MPQ" )
54+ . SetMainInstruction ( "Couldn't parse game MPQ." )
55+ . SetContent ( e . Message + "\n \n Are you using modified game files?" )
56+ . WithButton ( "Ok" , false )
57+ . Build ( ) ) ;
58+ m = null ;
59+ return false ;
60+ }
61+ }
62+
63+ public bool Initialize ( Engine engine )
3564 {
3665 this . engine = engine ;
66+ if ( ! TryOpenMpq ( out mpq ) )
67+ {
68+ OnFailedInitialize ? . Invoke ( ) ;
69+ waitForInitialized . SetResult ( false ) ;
70+ waitForInitialized = new ( ) ;
71+ return false ;
72+ }
3773 coroutineManager = new ( ) ;
3874 TimeManager = new TimeManager ( this ) ;
3975 ScreenSpaceSelector = new ScreenSpaceSelector ( this ) ;
@@ -51,16 +87,17 @@ public void Initialize(Engine engine)
5187
5288 OnInitialized ? . Invoke ( ) ;
5389 IsInitialized = true ;
54- waitForInitialized . SetResult ( ) ;
90+ waitForInitialized . SetResult ( true ) ;
91+ return true ;
5592 }
5693
5794 public void StartCoroutine ( IEnumerator coroutine )
5895 {
5996 coroutineManager . Start ( coroutine ) ;
6097 }
6198
62- private TaskCompletionSource waitForInitialized = new ( ) ;
63- public Task WaitForInitialized => waitForInitialized . Task ;
99+ private TaskCompletionSource < bool > waitForInitialized = new ( ) ;
100+ public Task < bool > WaitForInitialized => waitForInitialized . Task ;
64101
65102 private Material ? prevMaterial ;
66103 public void Update ( float delta )
@@ -108,7 +145,8 @@ public void SetMap(int mapId)
108145
109146 public void DoDispose ( )
110147 {
111- RequestDispose ? . Invoke ( ) ;
148+ if ( IsInitialized )
149+ RequestDispose ? . Invoke ( ) ;
112150 Debug . Assert ( ! IsInitialized ) ;
113151 }
114152
@@ -125,6 +163,8 @@ public void DisposeGame()
125163 MdxManager . Dispose ( ) ;
126164 TextureManager . Dispose ( ) ;
127165 MeshManager . Dispose ( ) ;
166+ mpq . Dispose ( ) ;
167+ mpq = null ! ;
128168 coroutineManager = null ! ;
129169 TimeManager = null ! ;
130170 ScreenSpaceSelector = null ! ;
@@ -143,6 +183,7 @@ public void DisposeGame()
143183
144184 public Engine Engine => engine ;
145185
186+ private IMpqArchive mpq ;
146187 private CoroutineManager coroutineManager ;
147188 public TimeManager TimeManager { get ; private set ; }
148189 public ScreenSpaceSelector ScreenSpaceSelector { get ; private set ; }
0 commit comments