@@ -341,11 +341,14 @@ public async Task ToggleModPackStatus(string modPackName, bool enable)
341
341
/// Performs the most low-level mod enable/disable functions, without saving the modlist,
342
342
/// ergo this should only be called by functions which will handle saving the modlist after
343
343
/// they're done performing all modlist operations.
344
+ ///
345
+ /// If the Index and modlist are provided, the actions are only applied to those cached entries, rather
346
+ /// than to the live files.
344
347
/// </summary>
345
348
/// <param name="enable"></param>
346
349
/// <param name="mod"></param>
347
350
/// <returns></returns>
348
- public async Task < bool > ToggleModUnsafe ( bool enable , Mod mod , bool includeInternal , bool updateCache )
351
+ public async Task < bool > ToggleModUnsafe ( bool enable , Mod mod , bool includeInternal , bool updateCache , IndexFile cachedIndex = null , ModList cachedModlist = null )
349
352
{
350
353
if ( mod == null ) return false ;
351
354
if ( string . IsNullOrEmpty ( mod . name ) ) return false ;
@@ -373,36 +376,66 @@ public async Task<bool> ToggleModUnsafe(bool enable, Mod mod, bool includeIntern
373
376
// Added file.
374
377
if ( enable && ! mod . enabled )
375
378
{
376
- await index . UpdateDataOffset ( mod . data . modOffset , mod . fullPath , updateCache ) ;
379
+ if ( cachedIndex != null )
380
+ {
381
+ cachedIndex . SetDataOffset ( mod . fullPath , mod . data . modOffset ) ;
382
+ }
383
+ else
384
+ {
385
+ await index . UpdateDataOffset ( mod . data . modOffset , mod . fullPath , false ) ;
386
+ }
377
387
mod . enabled = true ;
378
388
379
- // Check if we're re-enabling a metadata mod.
380
- var ext = Path . GetExtension ( mod . fullPath ) ;
381
- if ( ext == ".meta" )
389
+ if ( cachedIndex == null )
382
390
{
383
- // Retreive the uncompressed meta entry we just enabled.
384
- var data = await dat . GetType2Data ( mod . fullPath , false ) ;
385
- var meta = await ItemMetadata . Deserialize ( data ) ;
391
+ // Check if we're re-enabling a metadata mod.
392
+ var ext = Path . GetExtension ( mod . fullPath ) ;
393
+ if ( ext == ".meta" )
394
+ {
395
+ var df = IOUtil . GetDataFileFromPath ( mod . fullPath ) ;
396
+ // Retreive the uncompressed meta entry we just enabled.
397
+ var data = await dat . GetType2Data ( mod . data . modOffset , df ) ;
398
+ var meta = await ItemMetadata . Deserialize ( data ) ;
386
399
387
- meta . Validate ( mod . fullPath ) ;
400
+ meta . Validate ( mod . fullPath ) ;
388
401
389
- // And write that metadata to the actual constituent files.
390
- await ItemMetadata . ApplyMetadata ( meta ) ;
402
+ // And write that metadata to the actual constituent files.
403
+ await ItemMetadata . ApplyMetadata ( meta , cachedIndex , cachedModlist ) ;
404
+ }
391
405
}
392
406
}
393
407
else if ( ! enable && mod . enabled )
394
408
{
395
409
if ( mod . IsCustomFile ( ) )
396
410
{
397
411
// Delete file descriptor handles removing metadata as needed on its own.
398
- await index . DeleteFileDescriptor ( mod . fullPath , IOUtil . GetDataFileFromPath ( mod . fullPath ) , updateCache ) ;
412
+ if ( cachedIndex != null )
413
+ {
414
+ cachedIndex . SetDataOffset ( mod . fullPath , 0 ) ;
415
+ }
416
+ else
417
+ {
418
+ await index . DeleteFileDescriptor ( mod . fullPath , IOUtil . GetDataFileFromPath ( mod . fullPath ) , false ) ;
419
+ }
399
420
} else
400
421
{
401
- await index . UpdateDataOffset ( mod . data . originalOffset , mod . fullPath , updateCache ) ;
422
+ if ( cachedIndex != null )
423
+ {
424
+ cachedIndex . SetDataOffset ( mod . fullPath , mod . data . originalOffset ) ;
425
+ }
426
+ else
427
+ {
428
+ await index . UpdateDataOffset ( mod . data . originalOffset , mod . fullPath , false ) ;
429
+ }
402
430
}
403
431
mod . enabled = false ;
404
432
}
405
-
433
+
434
+ if ( updateCache )
435
+ {
436
+ XivCache . QueueDependencyUpdate ( mod . fullPath ) ;
437
+ }
438
+
406
439
return true ;
407
440
}
408
441
@@ -422,41 +455,77 @@ public async Task ToggleAllMods(bool enable, IProgress<(int current, int total,
422
455
// potentially pollute our index backups.
423
456
bool includeInternal = enable == false ;
424
457
458
+ Dictionary < XivDataFile , IndexFile > indexFiles = new Dictionary < XivDataFile , IndexFile > ( ) ;
459
+
425
460
426
461
var modNum = 0 ;
427
- foreach ( var modEntry in modList . Mods )
462
+ var mods = modList . Mods . ToList ( ) ;
463
+ foreach ( var modEntry in mods )
428
464
{
429
465
// Save disabling these for last.
430
466
if ( modEntry . IsInternal ( ) ) continue ;
431
467
432
- await ToggleModUnsafe ( enable , modEntry , false , false ) ;
468
+ var df = IOUtil . GetDataFileFromPath ( modEntry . fullPath ) ;
469
+ if ( ! indexFiles . ContainsKey ( df ) )
470
+ {
471
+ indexFiles . Add ( df , await index . GetIndexFile ( df ) ) ;
472
+ }
473
+
474
+
475
+ await ToggleModUnsafe ( enable , modEntry , false , false , indexFiles [ df ] , modList ) ;
433
476
progress ? . Report ( ( ++ modNum , modList . Mods . Count , string . Empty ) ) ;
434
477
}
435
478
436
- if ( includeInternal && ! enable )
479
+ if ( ! enable )
437
480
{
438
481
// Disable these last.
439
- var internalEntries = modList . Mods . Where ( x => x . IsInternal ( ) ) ;
482
+ var internalEntries = modList . Mods . Where ( x => x . IsInternal ( ) ) . ToList ( ) ;
440
483
foreach ( var modEntry in internalEntries )
441
484
{
442
- await ToggleModUnsafe ( enable , modEntry , true , false ) ;
485
+ var df = IOUtil . GetDataFileFromPath ( modEntry . fullPath ) ;
486
+ await ToggleModUnsafe ( enable , modEntry , true , false , indexFiles [ df ] , modList ) ;
487
+ modList . Mods . Remove ( modEntry ) ;
443
488
}
444
- }
489
+ } else
490
+ {
491
+ progress ? . Report ( ( 0 , 0 , "Expanding Metadata Entries..." ) ) ;
445
492
493
+ // Batch and group apply the metadata entries.
494
+ var metadataEntries = modList . Mods . Where ( x => x . fullPath . EndsWith ( ".meta" ) ) . ToList ( ) ;
495
+ var _dat = new Dat ( XivCache . GameInfo . GameDirectory ) ;
446
496
447
- SaveModList ( modList ) ;
497
+ Dictionary < XivDataFile , List < ItemMetadata > > metadata = new Dictionary < XivDataFile , List < ItemMetadata > > ( ) ;
498
+ foreach ( var mod in metadataEntries )
499
+ {
500
+ var df = IOUtil . GetDataFileFromPath ( mod . fullPath ) ;
501
+ var data = await _dat . GetType2Data ( mod . data . modOffset , df ) ;
502
+ var meta = await ItemMetadata . Deserialize ( data ) ;
448
503
449
- if ( includeInternal && ! enable )
450
- {
451
- // Now go ahead and delete the internal files, to prevent them
452
- // being accidentally re-enabled (They should be re-built by the metadata file imports)
453
- var internalEntries = modList . Mods . Where ( x => x . IsInternal ( ) ) ;
454
- foreach ( var modEntry in internalEntries )
504
+ meta . Validate ( mod . fullPath ) ;
505
+
506
+ if ( ! metadata . ContainsKey ( df ) )
507
+ {
508
+ metadata . Add ( df , new List < ItemMetadata > ( ) ) ;
509
+ }
510
+ metadata [ df ] . Add ( meta ) ;
511
+ }
512
+
513
+
514
+ foreach ( var dkv in metadata )
455
515
{
456
- await DeleteMod ( modEntry . fullPath , true ) ;
516
+ var df = dkv . Key ;
517
+ await ItemMetadata . ApplyMetadataBatched ( dkv . Value , indexFiles [ df ] , modList ) ;
457
518
}
458
519
}
459
520
521
+ foreach ( var kv in indexFiles )
522
+ {
523
+ await index . SaveIndexFile ( kv . Value ) ;
524
+ }
525
+
526
+ SaveModList ( modList ) ;
527
+
528
+
460
529
461
530
// Do these as a batch query at the end.
462
531
progress ? . Report ( ( ++ modNum , modList . Mods . Count , "Adding modified files to Cache Queue..." ) ) ;
0 commit comments