@@ -30,24 +30,20 @@ public class GameScannnerManager : IDisposable
3030
3131 private bool _scanIsRunning ;
3232
33- private readonly bool _useChunkDownloader ;
34-
3533 private CancellationTokenSource _cts ;
3634
3735 private IEnumerable < GameFileInfo > _gameFiles ;
3836
39- public GameScannnerManager ( bool useChunkDownloader = false , bool isSteam = false ) : this ( GetGameFilesRootPath ( ) ,
40- useChunkDownloader , isSteam )
37+ public GameScannnerManager ( bool isSteam = false ) : this ( GetGameFilesRootPath ( ) , isSteam )
4138 {
4239 }
4340
44- public GameScannnerManager ( string filesRootPath , bool useChunkDownloader , bool isSteam = false )
41+ public GameScannnerManager ( string filesRootPath , bool isSteam = false )
4542 {
4643 if ( string . IsNullOrEmpty ( filesRootPath ) )
47- throw new ArgumentException ( "Game files path is null or empty! " , nameof ( filesRootPath ) ) ;
44+ throw new ArgumentException ( "Game files path is null or empty" , nameof ( filesRootPath ) ) ;
4845
4946 _filesRootPath = filesRootPath ;
50- _useChunkDownloader = useChunkDownloader ;
5147 _isSteam = isSteam ;
5248 _scanIsRunning = false ;
5349 }
@@ -72,38 +68,33 @@ public async Task InitializeFromCelesteManifest()
7268
7369 CleanUpTmpFolder ( ) ;
7470
75- //
7671 var gameFileInfos = await GameFilesInfoFromCelesteManifest ( _isSteam ) ;
77- var fileInfos = gameFileInfos as GameFileInfo [ ] ?? gameFileInfos . ToArray ( ) ;
78- if ( ! fileInfos . Any ( ) )
79- throw new ArgumentException ( "Game files info is null or empty! " , nameof ( gameFileInfos ) ) ;
72+ var gamesFiles = gameFileInfos as GameFileInfo [ ] ?? gameFileInfos . ToArray ( ) ;
73+ if ( ! gamesFiles . Any ( ) )
74+ throw new ArgumentException ( "Game files info is null or empty" , nameof ( gameFileInfos ) ) ;
8075
81- _gameFiles = fileInfos ;
76+ _gameFiles = gamesFiles ;
8277 }
8378
84- public async Task InitializeFromGameManifest ( string type , int build )
79+ public async Task InitializeFromGameManifest ( )
8580 {
8681 if ( _gameFiles ? . Any ( ) == true )
8782 throw new Exception ( "Already Initialized" ) ;
8883
8984 CleanUpTmpFolder ( ) ;
9085
91- //
9286 var gameFileInfos = await GameFilesInfoFromCelesteManifest ( _isSteam ) ;
9387 var fileInfos = gameFileInfos as GameFileInfo [ ] ?? gameFileInfos . ToArray ( ) ;
9488 if ( ! fileInfos . Any ( ) )
95- throw new ArgumentException ( "Game files info is null or empty! " , nameof ( gameFileInfos ) ) ;
89+ throw new ArgumentException ( "Game files info is null or empty" , nameof ( gameFileInfos ) ) ;
9690
9791 _gameFiles = fileInfos ;
9892 }
9993
10094 public async Task < bool > Scan ( bool quick = true , IProgress < ScanProgress > progress = null )
10195 {
102- if ( _gameFiles == null || ! _gameFiles . Any ( ) )
103- throw new Exception ( "Not Initialized" ) ;
104-
105- if ( _scanIsRunning )
106- throw new Exception ( "Scan already running!" ) ;
96+ EnsureInitialized ( ) ;
97+ EnsureGameScannerIsNotRunning ( ) ;
10798
10899 _scanIsRunning = true ;
109100
@@ -115,8 +106,6 @@ public async Task<bool> Scan(bool quick = true, IProgress<ScanProgress> progress
115106 _cts = new CancellationTokenSource ( ) ;
116107 var token = _cts . Token ;
117108
118- //
119-
120109 var totalSize = _gameFiles . Select ( key => key . Size ) . Sum ( ) ;
121110 var currentSize = 0L ;
122111 var index = 0 ;
@@ -179,17 +168,13 @@ public async Task<bool> Scan(bool quick = true, IProgress<ScanProgress> progress
179168 public async Task < bool > ScanAndRepair ( IProgress < ScanProgress > progress = null ,
180169 IProgress < ScanSubProgress > subProgress = null )
181170 {
182- if ( _gameFiles == null || ! _gameFiles . Any ( ) )
183- throw new Exception ( "Not Initialized" ) ;
184-
185- if ( _scanIsRunning )
186- throw new Exception ( "Scan already running!" ) ;
171+ EnsureInitialized ( ) ;
172+ EnsureGameScannerIsNotRunning ( ) ;
187173
188174 _scanIsRunning = true ;
189175
190176 try
191177 {
192- //
193178 if ( _cts != null )
194179 {
195180 _cts . Cancel ( ) ;
@@ -200,13 +185,10 @@ public async Task<bool> ScanAndRepair(IProgress<ScanProgress> progress = null,
200185
201186 var token = _cts . Token ;
202187
203- //
204188 CleanUpTmpFolder ( ) ;
205189
206- //
207190 var retVal = false ;
208191
209- //
210192 var totalSize = _gameFiles . Select ( key => key . BinSize ) . Sum ( ) ;
211193 var globalProgress = 0L ;
212194 var totalIndex = _gameFiles . Count ( ) ;
@@ -221,7 +203,7 @@ public async Task<bool> ScanAndRepair(IProgress<ScanProgress> progress = null,
221203 progress ? . Report ( new ScanProgress ( fileInfo . FileName ,
222204 ( double ) globalProgress / totalSize * 100 , i , totalIndex ) ) ;
223205
224- retVal = await ScanAndRepairFile ( fileInfo , _filesRootPath , _useChunkDownloader , subProgress , token ) ;
206+ retVal = await ScanAndRepairFile ( fileInfo , _filesRootPath , subProgress , token ) ;
225207
226208 if ( ! retVal )
227209 break ;
@@ -248,6 +230,18 @@ public void Abort()
248230 _cts . Cancel ( ) ;
249231 }
250232
233+ private void EnsureInitialized ( )
234+ {
235+ if ( _gameFiles == null || ! _gameFiles . Any ( ) )
236+ throw new Exception ( "Game scanner has not been initialized or no game files was found" ) ;
237+ }
238+
239+ private void EnsureGameScannerIsNotRunning ( )
240+ {
241+ if ( _scanIsRunning )
242+ throw new Exception ( "Scan is already running" ) ;
243+ }
244+
251245 private static void CleanUpTmpFolder ( )
252246 {
253247 if ( ! Directory . Exists ( GameScannerTempPath ) )
@@ -280,23 +274,38 @@ private static void CleanUpTmpFolder()
280274
281275 #region GameFile
282276
283- public static async Task < bool > RunFileCheck ( string filePath , long fileSize , uint fileCrc32 ,
284- CancellationToken ct = default ,
285- IProgress < double > progress = null )
277+ public static async Task EnsureValidGameFile ( string gameFilePath , long expectedFileSize , uint expectedCrc32 ,
278+ CancellationToken ct = default , IProgress < double > progress = null )
286279 {
287- return RunFileQuickCheck ( filePath , fileSize ) &&
288- fileCrc32 == await Crc32Utils . DoGetCrc32FromFile ( filePath , ct , progress ) ;
280+ var gameFileInfo = new FileInfo ( gameFilePath ) ;
281+
282+ if ( ! gameFileInfo . Exists )
283+ throw new Exception ( $ "The game file { gameFilePath } does not exist") ;
284+
285+ if ( gameFileInfo . Length != expectedFileSize )
286+ throw new Exception ( $ "The game file { gameFilePath } was expected to have a size of { expectedFileSize } but was { gameFileInfo . Length } ") ;
287+
288+ var gameFileCrc32 = await Crc32Utils . DoGetCrc32FromFile ( gameFilePath , ct , progress ) ;
289+
290+ if ( gameFileCrc32 != expectedCrc32 )
291+ throw new Exception ( $ "The game file { gameFilePath } was expected to have a crc32 { expectedCrc32 } but was { gameFileCrc32 } ") ;
289292 }
290293
291- public static bool RunFileQuickCheck ( string filePath , long fileSize )
294+ public static async Task < bool > RunFileCheck ( string gameFilePath , long expectedFileSize , uint expectedCrc32 ,
295+ CancellationToken ct = default , IProgress < double > progress = null )
292296 {
293- var fi = new FileInfo ( filePath ) ;
294- return fi . Exists && fi . Length == fileSize ;
297+ return RunFileQuickCheck ( gameFilePath , expectedFileSize ) &&
298+ expectedCrc32 == await Crc32Utils . DoGetCrc32FromFile ( gameFilePath , ct , progress ) ;
299+ }
300+
301+ public static bool RunFileQuickCheck ( string gameFilePath , long expectedFileSize )
302+ {
303+ var fi = new FileInfo ( gameFilePath ) ;
304+ return fi . Exists && fi . Length == expectedFileSize ;
295305 }
296306
297307 public static async Task < bool > ScanAndRepairFile ( GameFileInfo fileInfo , string gameFilePath ,
298- bool useChunkDownloader = false , IProgress < ScanSubProgress > progress = null ,
299- CancellationToken ct = default )
308+ IProgress < ScanSubProgress > progress = null , CancellationToken ct = default )
300309 {
301310 var filePath = Path . Combine ( gameFilePath , fileInfo . FileName ) ;
302311
@@ -364,15 +373,8 @@ public static async Task<bool> ScanAndRepairFile(GameFileInfo fileInfo, string g
364373 }
365374 } ;
366375
367- try
368- {
369- await fileDownloader . DownloadAsync ( ct ) ;
370- }
371- catch ( Exception e )
372- {
373- throw new Exception ( $ "Downloaded file '{ fileInfo . FileName } ' failed!\r \n " +
374- $ "{ e . Message } ") ;
375- }
376+ await fileDownloader . DownloadAsync ( ct ) ;
377+
376378
377379 //#3 Check Downloaded File
378380 ct . ThrowIfCancellationRequested ( ) ;
@@ -390,12 +392,16 @@ public static async Task<bool> ScanAndRepairFile(GameFileInfo fileInfo, string g
390392 } ;
391393 }
392394
393- if ( ! await RunFileCheck ( tempFileName , fileInfo . BinSize , fileInfo . BinCrc32 , ct , subProgressCheckDown ) )
395+ try
396+ {
397+ await EnsureValidGameFile ( tempFileName , fileInfo . BinSize , fileInfo . BinCrc32 , ct , subProgressCheckDown ) ;
398+ }
399+ catch
394400 {
395401 if ( File . Exists ( tempFileName ) )
396402 File . Delete ( tempFileName ) ;
397403
398- throw new Exception ( $ "Downloaded file ' { fileInfo . FileName } ' is invalid!" ) ;
404+ throw ;
399405 }
400406
401407 //#4 Extract downloaded file
@@ -424,7 +430,6 @@ public static async Task<bool> ScanAndRepairFile(GameFileInfo fileInfo, string g
424430 Progress < double > subProgressCheckExt = null ;
425431 if ( progress != null )
426432 {
427- //
428433 progress . Report ( new ScanSubProgress (
429434 ScanSubProgressStep . CheckExtractDownload , 0 ) ) ;
430435
@@ -436,8 +441,7 @@ public static async Task<bool> ScanAndRepairFile(GameFileInfo fileInfo, string g
436441 } ;
437442 }
438443
439- if ( ! await RunFileCheck ( tempFileName2 , fileInfo . Size , fileInfo . Crc32 , ct , subProgressCheckExt ) )
440- throw new Exception ( $ "Extracted file '{ fileInfo . FileName } ' is invalid!") ;
444+ await EnsureValidGameFile ( tempFileName2 , fileInfo . Size , fileInfo . Crc32 , ct , subProgressCheckExt ) ;
441445
442446 File . Delete ( tempFileName ) ;
443447
@@ -582,14 +586,14 @@ public static async Task<IEnumerable<GameFileInfo>> GameFilesInfoFromCelesteMani
582586 . ToDictionary ( key => key . FileName , StringComparer . OrdinalIgnoreCase ) ;
583587
584588 //Load Celeste override
585- string json ;
589+ string manifestJsonContents ;
586590 using ( var client = new WebClient ( ) )
587591 {
588- json = await client . DownloadStringTaskAsync (
592+ manifestJsonContents = await client . DownloadStringTaskAsync (
589593 "https://downloads.projectceleste.com/game_files/manifest_override.json" ) ;
590594 }
591595
592- var filesInfoOverride = JsonConvert . DeserializeObject < GameFilesInfo > ( json ) . GameFileInfo . ToArray ( )
596+ var filesInfoOverride = JsonConvert . DeserializeObject < GameFilesInfo > ( manifestJsonContents ) . GameFileInfo . ToArray ( )
593597 . Select ( key => key . Value ) ;
594598
595599 foreach ( var fileInfo in filesInfoOverride )
@@ -614,22 +618,20 @@ public static async Task CreateUpdatePackage(string inputFolder, string outputFo
614618 baseHttpLink += "/" ;
615619 baseHttpLink = Path . Combine ( baseHttpLink , "bin_override" , buildId . ToString ( ) ) . Replace ( "\\ " , "/" ) ;
616620
617- var data = await GenerateGameFilesInfo ( inputFolder , finalOutputFolder , baseHttpLink , buildId , ct ) ;
621+ var gameFiles = await GenerateGameFilesInfo ( inputFolder , finalOutputFolder , baseHttpLink , buildId , ct ) ;
618622
619- if ( data . GameFileInfo . Count < 1 )
620- throw new Exception ( "FileInfo.Count < 1 ") ;
623+ if ( gameFiles . GameFileInfo . Count < 1 )
624+ throw new Exception ( $ "No game files found in { inputFolder } ") ;
621625
622- //Json
623- var json = JsonConvert . SerializeObject ( data , Formatting . Indented ) ;
624- File . WriteAllText ( Path . Combine ( finalOutputFolder , $ "manifest_override-{ buildId } .json") , json ,
626+ var manifestJsonContents = JsonConvert . SerializeObject ( gameFiles , Formatting . Indented ) ;
627+ File . WriteAllText ( Path . Combine ( finalOutputFolder , $ "manifest_override-{ buildId } .json") , manifestJsonContents ,
625628 Encoding . UTF8 ) ;
626- File . WriteAllText ( Path . Combine ( outputFolder , "manifest_override.json" ) , json , Encoding . UTF8 ) ;
629+ File . WriteAllText ( Path . Combine ( outputFolder , "manifest_override.json" ) , manifestJsonContents , Encoding . UTF8 ) ;
627630
628- //Xml
629- var xml = data . SerializeToXml ( ) ;
630- File . WriteAllText ( Path . Combine ( finalOutputFolder , $ "manifest_override-{ buildId } .xml") , xml ,
631+ var manifestXmlContents = gameFiles . SerializeToXml ( ) ;
632+ File . WriteAllText ( Path . Combine ( finalOutputFolder , $ "manifest_override-{ buildId } .xml") , manifestXmlContents ,
631633 Encoding . UTF8 ) ;
632- File . WriteAllText ( Path . Combine ( outputFolder , "manifest_override.xml" ) , xml , Encoding . UTF8 ) ;
634+ File . WriteAllText ( Path . Combine ( outputFolder , "manifest_override.xml" ) , manifestXmlContents , Encoding . UTF8 ) ;
633635 }
634636
635637 private static async Task < GameFilesInfo > GenerateGameFilesInfo ( string inputFolder , string outputFolder ,
@@ -643,10 +645,8 @@ private static async Task<GameFilesInfo> GenerateGameFilesInfo(string inputFolde
643645 var newFilesInfo = new List < GameFileInfo > ( ) ;
644646 foreach ( var file in Directory . GetFiles ( inputFolder , "*" , SearchOption . AllDirectories ) )
645647 {
646- //
647648 ct . ThrowIfCancellationRequested ( ) ;
648649
649- //
650650 var rootPath = inputFolder ;
651651 if ( ! rootPath . EndsWith ( Path . DirectorySeparatorChar . ToString ( ) ) )
652652 rootPath += Path . DirectorySeparatorChar ;
@@ -679,10 +679,8 @@ private static async Task<GameFileInfo> GenerateGameFileInfo(string file, string
679679 var outFileCrc = await Crc32Utils . DoGetCrc32FromFile ( outFileName , ct ) ;
680680 var outFileLength = new FileInfo ( outFileName ) . Length ;
681681
682- var fileInfo = new GameFileInfo ( fileName , fileCrc , fileLength , externalLocation ,
682+ return new GameFileInfo ( fileName , fileCrc , fileLength , externalLocation ,
683683 outFileCrc , outFileLength ) ;
684-
685- return fileInfo ;
686684 }
687685
688686 #endregion
0 commit comments