1414using Microsoft . Win32 ;
1515using System ;
1616using System . Buffers . Binary ;
17+ using System . Collections . Concurrent ;
1718using System . Collections . Generic ;
1819using System . Data ;
1920using System . IO ;
@@ -319,9 +320,18 @@ private async Task BuildAndEnumerateVideoVersioningFile(CancellationToken token,
319320 // Get the base URL
320321 string baseURL = CombineURLFromString ( ( GetAppConfigValue ( "EnableHTTPRepairOverride" ) . ToBool ( ) ? "http://" : "https://" ) + assetBundleURL , "/Video/" ) ;
321322
323+ // Get FileInfo of the version.txt file
324+ FileInfo fileInfo = new FileInfo ( Path . Combine ( _gamePath ! , NormalizePath ( _videoBaseLocalPath ) ! , "Version.txt" ) )
325+ . EnsureCreationOfDirectory ( )
326+ . EnsureNoReadOnly ( ) ;
327+
322328 // Build video versioning file
323- await using StreamWriter sw = new StreamWriter ( Path . Combine ( _gamePath ! , NormalizePath ( _videoBaseLocalPath ) ! , "Version.txt" ) , false ) ;
324- // Iterate the metadata to be converted into asset index in parallel
329+ await using TextWriter sw = fileInfo . CreateText ( ) ;
330+
331+ // Initialize concurrent queue for video metadata
332+ ConcurrentDictionary < string , CGMetadata > videoMetadataQueue = new ConcurrentDictionary < string , CGMetadata > ( ) ;
333+
334+ // Iterate the metadata to be converted into asset index
325335 await Parallel . ForEachAsync ( enumEntry ! , new ParallelOptions
326336 {
327337 CancellationToken = token ,
@@ -333,14 +343,6 @@ private async Task BuildAndEnumerateVideoVersioningFile(CancellationToken token,
333343 // Starting from 7.1, the CGs that have included in ignoredAssetIDs (which is marked as deleted) will be ignored.
334344 bool isCGAvailable = await IsCGFileAvailable ( metadata , baseURL , tokenInternal ) ;
335345 bool isCGIgnored = ignoredAssetIDs . IgnoredVideoCGSubCategory . Contains ( metadata ! . CgSubCategory ) ;
336- if ( ! metadata . InStreamingAssets )
337- {
338- lock ( sw )
339- {
340- // Append the versioning list
341- sw . WriteLine ( "Video/" + ( _audioLanguage == AudioLanguageType . Japanese ? metadata . CgPathHighBitrateJP : metadata . CgPathHighBitrateCN ) + ".usm\t 1" ) ;
342- }
343- }
344346
345347 #if DEBUG
346348 if ( isCGIgnored )
@@ -350,18 +352,26 @@ private async Task BuildAndEnumerateVideoVersioningFile(CancellationToken token,
350352 if ( ! metadata . InStreamingAssets && isCGAvailable && ! isCGIgnored )
351353 {
352354 string name = ( _audioLanguage == AudioLanguageType . Japanese ? metadata . CgPathHighBitrateJP : metadata . CgPathHighBitrateCN ) + ".usm" ;
353- lock ( assetIndex )
354- {
355- assetIndex . Add ( new FilePropertiesRemote
356- {
357- N = CombineURLFromString ( _videoBaseLocalPath , name ) ,
358- RN = CombineURLFromString ( baseURL , name ) ,
359- S = _audioLanguage == AudioLanguageType . Japanese ? metadata . FileSizeHighBitrateJP : metadata . FileSizeHighBitrateCN ,
360- FT = FileType . Video
361- } ) ;
362- }
355+ _ = videoMetadataQueue . TryAdd ( name , metadata ) ;
363356 }
364357 } ) ;
358+
359+ foreach ( KeyValuePair < string , CGMetadata > metadata in videoMetadataQueue )
360+ {
361+ assetIndex . Add ( new FilePropertiesRemote
362+ {
363+ N = CombineURLFromString ( _videoBaseLocalPath , metadata . Key ) ,
364+ RN = CombineURLFromString ( baseURL , metadata . Key ) ,
365+ S = _audioLanguage == AudioLanguageType . Japanese ? metadata . Value . FileSizeHighBitrateJP : metadata . Value . FileSizeHighBitrateCN ,
366+ FT = FileType . Video
367+ } ) ;
368+
369+ if ( ! metadata . Value . InStreamingAssets )
370+ {
371+ // Append the versioning list
372+ await sw . WriteLineAsync ( "Video/" + ( _audioLanguage == AudioLanguageType . Japanese ? metadata . Value . CgPathHighBitrateJP : metadata . Value . CgPathHighBitrateCN ) + ".usm\t 1" ) ;
373+ }
374+ }
365375 }
366376
367377 private async ValueTask < bool > IsCGFileAvailable ( CGMetadata cgInfo , string baseURL , CancellationToken token )
0 commit comments