Skip to content

Commit d848bd4

Browse files
committed
Added proper batch functionality to Enable All/Disable All mods.
1 parent 9dc1cb4 commit d848bd4

File tree

1 file changed

+97
-28
lines changed

1 file changed

+97
-28
lines changed

xivModdingFramework/Mods/Modding.cs

Lines changed: 97 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,14 @@ public async Task ToggleModPackStatus(string modPackName, bool enable)
341341
/// Performs the most low-level mod enable/disable functions, without saving the modlist,
342342
/// ergo this should only be called by functions which will handle saving the modlist after
343343
/// 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.
344347
/// </summary>
345348
/// <param name="enable"></param>
346349
/// <param name="mod"></param>
347350
/// <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)
349352
{
350353
if (mod == null) return false;
351354
if (string.IsNullOrEmpty(mod.name)) return false;
@@ -373,36 +376,66 @@ public async Task<bool> ToggleModUnsafe(bool enable, Mod mod, bool includeIntern
373376
// Added file.
374377
if (enable && !mod.enabled)
375378
{
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+
}
377387
mod.enabled = true;
378388

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)
382390
{
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);
386399

387-
meta.Validate(mod.fullPath);
400+
meta.Validate(mod.fullPath);
388401

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+
}
391405
}
392406
}
393407
else if (!enable && mod.enabled)
394408
{
395409
if (mod.IsCustomFile())
396410
{
397411
// 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+
}
399420
} else
400421
{
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+
}
402430
}
403431
mod.enabled = false;
404432
}
405-
433+
434+
if (updateCache)
435+
{
436+
XivCache.QueueDependencyUpdate(mod.fullPath);
437+
}
438+
406439
return true;
407440
}
408441

@@ -422,41 +455,77 @@ public async Task ToggleAllMods(bool enable, IProgress<(int current, int total,
422455
// potentially pollute our index backups.
423456
bool includeInternal = enable == false;
424457

458+
Dictionary<XivDataFile, IndexFile> indexFiles = new Dictionary<XivDataFile, IndexFile>();
459+
425460

426461
var modNum = 0;
427-
foreach (var modEntry in modList.Mods)
462+
var mods = modList.Mods.ToList();
463+
foreach (var modEntry in mods)
428464
{
429465
// Save disabling these for last.
430466
if (modEntry.IsInternal()) continue;
431467

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);
433476
progress?.Report((++modNum, modList.Mods.Count, string.Empty));
434477
}
435478

436-
if (includeInternal && !enable)
479+
if (!enable)
437480
{
438481
// Disable these last.
439-
var internalEntries = modList.Mods.Where(x => x.IsInternal());
482+
var internalEntries = modList.Mods.Where(x => x.IsInternal()).ToList();
440483
foreach (var modEntry in internalEntries)
441484
{
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);
443488
}
444-
}
489+
} else
490+
{
491+
progress?.Report((0, 0, "Expanding Metadata Entries..."));
445492

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);
446496

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);
448503

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)
455515
{
456-
await DeleteMod(modEntry.fullPath, true);
516+
var df = dkv.Key;
517+
await ItemMetadata.ApplyMetadataBatched(dkv.Value, indexFiles[df], modList);
457518
}
458519
}
459520

521+
foreach (var kv in indexFiles)
522+
{
523+
await index.SaveIndexFile(kv.Value);
524+
}
525+
526+
SaveModList(modList);
527+
528+
460529

461530
// Do these as a batch query at the end.
462531
progress?.Report((++modNum, modList.Mods.Count, "Adding modified files to Cache Queue..."));

0 commit comments

Comments
 (0)