mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-31 21:03:48 +01:00
Make saving files and recalculating effective files threaded/once per frame.
This commit is contained in:
parent
b8210e094b
commit
67de0ccf45
14 changed files with 147 additions and 42 deletions
|
|
@ -177,7 +177,10 @@ public partial class ModCollection
|
|||
|
||||
|
||||
public void SaveActiveCollections()
|
||||
=> SaveActiveCollections( Default.Name, Current.Name, Characters.Select( kvp => ( kvp.Key, kvp.Value.Name ) ) );
|
||||
{
|
||||
Penumbra.Framework.RegisterDelayed( nameof( SaveActiveCollections ),
|
||||
() => SaveActiveCollections( Default.Name, Current.Name, Characters.Select( kvp => ( kvp.Key, kvp.Value.Name ) ) ) );
|
||||
}
|
||||
|
||||
internal static void SaveActiveCollections( string def, string current, IEnumerable< (string, string) > characters )
|
||||
{
|
||||
|
|
@ -203,7 +206,7 @@ public partial class ModCollection
|
|||
|
||||
j.WriteEndObject();
|
||||
j.WriteEndObject();
|
||||
PluginLog.Verbose( "Active Collections saved." );
|
||||
PluginLog.Verbose( "Active Collections saved." );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Dalamud.Logging;
|
||||
using OtterGui.Classes;
|
||||
using Penumbra.GameData.ByteString;
|
||||
|
|
@ -61,9 +62,6 @@ public partial class ModCollection
|
|||
internal IReadOnlyDictionary< Utf8GamePath, FullPath > ResolvedFiles
|
||||
=> _cache?.ResolvedFiles ?? new Dictionary< Utf8GamePath, FullPath >();
|
||||
|
||||
internal IReadOnlySet< FullPath > MissingFiles
|
||||
=> _cache?.MissingFiles ?? new HashSet< FullPath >();
|
||||
|
||||
internal IReadOnlyDictionary< string, object? > ChangedItems
|
||||
=> _cache?.ChangedItems ?? new Dictionary< string, object? >();
|
||||
|
||||
|
|
@ -76,6 +74,10 @@ public partial class ModCollection
|
|||
// Update the effective file list for the given cache.
|
||||
// Creates a cache if necessary.
|
||||
public void CalculateEffectiveFileList( bool withMetaManipulations, bool reloadDefault )
|
||||
=> Penumbra.Framework.RegisterImportant( nameof( CalculateEffectiveFileList ) + Name,
|
||||
() => CalculateEffectiveFileListInternal( withMetaManipulations, reloadDefault ) );
|
||||
|
||||
private void CalculateEffectiveFileListInternal( bool withMetaManipulations, bool reloadDefault )
|
||||
{
|
||||
// Skip the empty collection.
|
||||
if( Index == 0 )
|
||||
|
|
@ -83,7 +85,7 @@ public partial class ModCollection
|
|||
return;
|
||||
}
|
||||
|
||||
PluginLog.Debug( "Recalculating effective file list for {CollectionName:l} [{WithMetaManipulations}] [{ReloadDefault}]", Name,
|
||||
PluginLog.Debug( "[{Thread}] Recalculating effective file list for {CollectionName:l} [{WithMetaManipulations}] [{ReloadDefault}]", Thread.CurrentThread.ManagedThreadId, Name,
|
||||
withMetaManipulations, reloadDefault );
|
||||
_cache ??= new Cache( this );
|
||||
_cache.CalculateEffectiveFileList( withMetaManipulations );
|
||||
|
|
@ -92,6 +94,7 @@ public partial class ModCollection
|
|||
SetFiles();
|
||||
Penumbra.ResidentResources.Reload();
|
||||
}
|
||||
PluginLog.Debug( "[{Thread}] Recalculation of effective file list for {CollectionName:l} finished.", Thread.CurrentThread.ManagedThreadId, Name);
|
||||
}
|
||||
|
||||
// Set Metadata files.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility;
|
||||
using Penumbra.GameData.ByteString;
|
||||
using Penumbra.Meta.Manager;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
|
|
@ -15,15 +18,12 @@ public partial class ModCollection
|
|||
// It will only be setup if a collection gets activated in any way.
|
||||
private class Cache : IDisposable
|
||||
{
|
||||
// Shared caches to avoid allocations.
|
||||
private static readonly Dictionary< Utf8GamePath, FileRegister > RegisteredFiles = new(1024);
|
||||
private static readonly Dictionary< MetaManipulation, FileRegister > RegisteredManipulations = new(1024);
|
||||
private static readonly List< ModSettings? > ResolvedSettings = new(128);
|
||||
private readonly Dictionary< Utf8GamePath, FileRegister > _registeredFiles = new();
|
||||
private readonly Dictionary< MetaManipulation, FileRegister > _registeredManipulations = new();
|
||||
|
||||
private readonly ModCollection _collection;
|
||||
private readonly SortedList< string, object? > _changedItems = new();
|
||||
public readonly Dictionary< Utf8GamePath, FullPath > ResolvedFiles = new();
|
||||
public readonly HashSet< FullPath > MissingFiles = new();
|
||||
public readonly MetaManager MetaManipulations;
|
||||
public ConflictCache Conflicts = new();
|
||||
|
||||
|
|
@ -96,14 +96,10 @@ public partial class ModCollection
|
|||
// Clear all local and global caches to prepare for recomputation.
|
||||
private void ClearStorageAndPrepare()
|
||||
{
|
||||
ResolvedFiles.Clear();
|
||||
MissingFiles.Clear();
|
||||
RegisteredFiles.Clear();
|
||||
_changedItems.Clear();
|
||||
ResolvedSettings.Clear();
|
||||
_registeredFiles.EnsureCapacity( 2 * ResolvedFiles.Count );
|
||||
ResolvedFiles.Clear();
|
||||
Conflicts.ClearFileConflicts();
|
||||
// Obtains actual settings for this collection with all inheritances.
|
||||
ResolvedSettings.AddRange( _collection.ActualSettings );
|
||||
}
|
||||
|
||||
// Recalculate all file changes from current settings. Include all fixed custom redirects.
|
||||
|
|
@ -113,7 +109,7 @@ public partial class ModCollection
|
|||
ClearStorageAndPrepare();
|
||||
if( withManipulations )
|
||||
{
|
||||
RegisteredManipulations.Clear();
|
||||
_registeredManipulations.EnsureCapacity( 2 * MetaManipulations.Count );
|
||||
MetaManipulations.Reset();
|
||||
}
|
||||
|
||||
|
|
@ -125,6 +121,10 @@ public partial class ModCollection
|
|||
|
||||
AddMetaFiles();
|
||||
++RecomputeCounter;
|
||||
_registeredFiles.Clear();
|
||||
_registeredFiles.TrimExcess();
|
||||
_registeredManipulations.Clear();
|
||||
_registeredManipulations.TrimExcess();
|
||||
}
|
||||
|
||||
// Identify and record all manipulated objects for this entire collection.
|
||||
|
|
@ -158,15 +158,15 @@ public partial class ModCollection
|
|||
// Inside the same mod, conflicts are not recorded.
|
||||
private void AddFile( Utf8GamePath path, FullPath file, FileRegister priority )
|
||||
{
|
||||
if( RegisteredFiles.TryGetValue( path, out var register ) )
|
||||
if( _registeredFiles.TryGetValue( path, out var register ) )
|
||||
{
|
||||
if( register.SameMod( priority, out var less ) )
|
||||
{
|
||||
Conflicts.AddConflict( register.ModIdx, priority.ModIdx, register.ModPriority, priority.ModPriority, path );
|
||||
if( less )
|
||||
{
|
||||
RegisteredFiles[ path ] = priority;
|
||||
ResolvedFiles[ path ] = file;
|
||||
_registeredFiles[ path ] = priority;
|
||||
ResolvedFiles[ path ] = file;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -176,14 +176,14 @@ public partial class ModCollection
|
|||
// Do not add conflicts.
|
||||
if( less )
|
||||
{
|
||||
RegisteredFiles[ path ] = priority;
|
||||
ResolvedFiles[ path ] = file;
|
||||
_registeredFiles[ path ] = priority;
|
||||
ResolvedFiles[ path ] = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // File not seen before, just add it.
|
||||
{
|
||||
RegisteredFiles.Add( path, priority );
|
||||
_registeredFiles.Add( path, priority );
|
||||
ResolvedFiles.Add( path, file );
|
||||
}
|
||||
}
|
||||
|
|
@ -194,14 +194,14 @@ public partial class ModCollection
|
|||
// Inside the same mod, conflicts are not recorded.
|
||||
private void AddManipulation( MetaManipulation manip, FileRegister priority )
|
||||
{
|
||||
if( RegisteredManipulations.TryGetValue( manip, out var register ) )
|
||||
if( _registeredManipulations.TryGetValue( manip, out var register ) )
|
||||
{
|
||||
if( register.SameMod( priority, out var less ) )
|
||||
{
|
||||
Conflicts.AddConflict( register.ModIdx, priority.ModIdx, register.ModPriority, priority.ModPriority, manip );
|
||||
if( less )
|
||||
{
|
||||
RegisteredManipulations[ manip ] = priority;
|
||||
_registeredManipulations[ manip ] = priority;
|
||||
MetaManipulations.ApplyMod( manip, priority.ModIdx );
|
||||
}
|
||||
}
|
||||
|
|
@ -212,14 +212,14 @@ public partial class ModCollection
|
|||
// Do not add conflicts.
|
||||
if( less )
|
||||
{
|
||||
RegisteredManipulations[ manip ] = priority;
|
||||
_registeredManipulations[ manip ] = priority;
|
||||
MetaManipulations.ApplyMod( manip, priority.ModIdx );
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Manipulation not seen before, just add it.
|
||||
{
|
||||
RegisteredManipulations[ manip ] = priority;
|
||||
_registeredManipulations[ manip ] = priority;
|
||||
MetaManipulations.ApplyMod( manip, priority.ModIdx );
|
||||
}
|
||||
}
|
||||
|
|
@ -250,7 +250,7 @@ public partial class ModCollection
|
|||
// Add all files and possibly manipulations of a given mod according to its settings in this collection.
|
||||
private void AddMod( int modIdx, bool withManipulations )
|
||||
{
|
||||
var settings = ResolvedSettings[ modIdx ];
|
||||
var settings = _collection[ modIdx ].Settings;
|
||||
if( settings is not { Enabled: true } )
|
||||
{
|
||||
return;
|
||||
|
|
@ -300,7 +300,7 @@ public partial class ModCollection
|
|||
Penumbra.Redirects.Apply( ResolvedFiles );
|
||||
foreach( var gamePath in ResolvedFiles.Keys )
|
||||
{
|
||||
RegisteredFiles.Add( gamePath, new FileRegister( -1, int.MaxValue, 0, 0 ) );
|
||||
_registeredFiles.Add( gamePath, new FileRegister( -1, int.MaxValue, 0, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public partial class ModCollection
|
|||
=> new(Path.Combine( CollectionDirectory, $"{Name.RemoveInvalidPathSymbols()}.json" ));
|
||||
|
||||
// Custom serialization due to shared mod information across managers.
|
||||
public void Save()
|
||||
private void SaveCollection()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -71,6 +71,9 @@ public partial class ModCollection
|
|||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
=> Penumbra.Framework.RegisterDelayed( nameof( SaveCollection ) + Name, SaveCollection );
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
if( Index == 0 )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue