mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-19 15:14:25 +01:00
Rework Interop/Loader Services.
This commit is contained in:
parent
99fd4b7806
commit
0df12a34cb
32 changed files with 1137 additions and 1421 deletions
|
|
@ -4,10 +4,12 @@ using Penumbra.Meta.Manager;
|
|||
using Penumbra.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using Penumbra.Interop;
|
||||
using Penumbra.Meta.Files;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
|
|
@ -28,10 +30,10 @@ public partial class ModCollection
|
|||
// Only create, do not update.
|
||||
private void CreateCache()
|
||||
{
|
||||
if( _cache == null )
|
||||
if (_cache == null)
|
||||
{
|
||||
CalculateEffectiveFileList();
|
||||
Penumbra.Log.Verbose( $"Created new cache for collection {Name}." );
|
||||
Penumbra.Log.Verbose($"Created new cache for collection {Name}.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -40,21 +42,17 @@ public partial class ModCollection
|
|||
=> CalculateEffectiveFileList();
|
||||
|
||||
// Handle temporary mods for this collection.
|
||||
public void Apply( Mod.TemporaryMod tempMod, bool created )
|
||||
public void Apply(Mod.TemporaryMod tempMod, bool created)
|
||||
{
|
||||
if( created )
|
||||
{
|
||||
_cache?.AddMod( tempMod, tempMod.TotalManipulations > 0 );
|
||||
}
|
||||
if (created)
|
||||
_cache?.AddMod(tempMod, tempMod.TotalManipulations > 0);
|
||||
else
|
||||
{
|
||||
_cache?.ReloadMod( tempMod, tempMod.TotalManipulations > 0 );
|
||||
}
|
||||
_cache?.ReloadMod(tempMod, tempMod.TotalManipulations > 0);
|
||||
}
|
||||
|
||||
public void Remove( Mod.TemporaryMod tempMod )
|
||||
public void Remove(Mod.TemporaryMod tempMod)
|
||||
{
|
||||
_cache?.RemoveMod( tempMod, tempMod.TotalManipulations > 0 );
|
||||
_cache?.RemoveMod(tempMod, tempMod.TotalManipulations > 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -63,123 +61,122 @@ public partial class ModCollection
|
|||
{
|
||||
_cache?.Dispose();
|
||||
_cache = null;
|
||||
Penumbra.Log.Verbose( $"Cleared cache of collection {Name}." );
|
||||
Penumbra.Log.Verbose($"Cleared cache of collection {Name}.");
|
||||
}
|
||||
|
||||
public IEnumerable< Utf8GamePath > ReverseResolvePath( FullPath path )
|
||||
=> _cache?.ReverseResolvePath( path ) ?? Array.Empty< Utf8GamePath >();
|
||||
public IEnumerable<Utf8GamePath> ReverseResolvePath(FullPath path)
|
||||
=> _cache?.ReverseResolvePath(path) ?? Array.Empty<Utf8GamePath>();
|
||||
|
||||
public HashSet< Utf8GamePath >[] ReverseResolvePaths( string[] paths )
|
||||
=> _cache?.ReverseResolvePaths( paths ) ?? paths.Select( _ => new HashSet< Utf8GamePath >() ).ToArray();
|
||||
public HashSet<Utf8GamePath>[] ReverseResolvePaths(string[] paths)
|
||||
=> _cache?.ReverseResolvePaths(paths) ?? paths.Select(_ => new HashSet<Utf8GamePath>()).ToArray();
|
||||
|
||||
public FullPath? ResolvePath( Utf8GamePath path )
|
||||
=> _cache?.ResolvePath( path );
|
||||
public FullPath? ResolvePath(Utf8GamePath path)
|
||||
=> _cache?.ResolvePath(path);
|
||||
|
||||
// Force a file to be resolved to a specific path regardless of conflicts.
|
||||
internal void ForceFile( Utf8GamePath path, FullPath fullPath )
|
||||
internal void ForceFile(Utf8GamePath path, FullPath fullPath)
|
||||
{
|
||||
if( CheckFullPath( path, fullPath ) )
|
||||
{
|
||||
_cache!.ResolvedFiles[ path ] = new ModPath( Mod.ForcedFiles, fullPath );
|
||||
}
|
||||
if (CheckFullPath(path, fullPath))
|
||||
_cache!.ResolvedFiles[path] = new ModPath(Mod.ForcedFiles, fullPath);
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
private static bool CheckFullPath( Utf8GamePath path, FullPath fullPath )
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool CheckFullPath(Utf8GamePath path, FullPath fullPath)
|
||||
{
|
||||
if( fullPath.InternalName.Length < Utf8GamePath.MaxGamePathLength )
|
||||
{
|
||||
if (fullPath.InternalName.Length < Utf8GamePath.MaxGamePathLength)
|
||||
return true;
|
||||
}
|
||||
|
||||
Penumbra.Log.Error( $"The redirected path is too long to add the redirection\n\t{path}\n\t--> {fullPath}" );
|
||||
Penumbra.Log.Error($"The redirected path is too long to add the redirection\n\t{path}\n\t--> {fullPath}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force a file resolve to be removed.
|
||||
internal void RemoveFile( Utf8GamePath path )
|
||||
=> _cache!.ResolvedFiles.Remove( path );
|
||||
internal void RemoveFile(Utf8GamePath path)
|
||||
=> _cache!.ResolvedFiles.Remove(path);
|
||||
|
||||
// Obtain data from the cache.
|
||||
internal MetaManager? MetaCache
|
||||
=> _cache?.MetaManipulations;
|
||||
|
||||
internal IReadOnlyDictionary< Utf8GamePath, ModPath > ResolvedFiles
|
||||
=> _cache?.ResolvedFiles ?? new Dictionary< Utf8GamePath, ModPath >();
|
||||
public bool GetImcFile(Utf8GamePath path, [NotNullWhen(true)] out ImcFile? file)
|
||||
{
|
||||
if (_cache != null)
|
||||
return _cache.MetaManipulations.GetImcFile(path, out file);
|
||||
|
||||
internal IReadOnlyDictionary< string, (SingleArray< IMod >, object?) > ChangedItems
|
||||
=> _cache?.ChangedItems ?? new Dictionary< string, (SingleArray< IMod >, object?) >();
|
||||
file = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal IEnumerable< SingleArray< ModConflicts > > AllConflicts
|
||||
=> _cache?.AllConflicts ?? Array.Empty< SingleArray< ModConflicts > >();
|
||||
internal IReadOnlyDictionary<Utf8GamePath, ModPath> ResolvedFiles
|
||||
=> _cache?.ResolvedFiles ?? new Dictionary<Utf8GamePath, ModPath>();
|
||||
|
||||
internal SingleArray< ModConflicts > Conflicts( Mod mod )
|
||||
=> _cache?.Conflicts( mod ) ?? new SingleArray< ModConflicts >();
|
||||
internal IReadOnlyDictionary<string, (SingleArray<IMod>, object?)> ChangedItems
|
||||
=> _cache?.ChangedItems ?? new Dictionary<string, (SingleArray<IMod>, object?)>();
|
||||
|
||||
internal IEnumerable<SingleArray<ModConflicts>> AllConflicts
|
||||
=> _cache?.AllConflicts ?? Array.Empty<SingleArray<ModConflicts>>();
|
||||
|
||||
internal SingleArray<ModConflicts> Conflicts(Mod mod)
|
||||
=> _cache?.Conflicts(mod) ?? new SingleArray<ModConflicts>();
|
||||
|
||||
// Update the effective file list for the given cache.
|
||||
// Creates a cache if necessary.
|
||||
public void CalculateEffectiveFileList()
|
||||
=> Penumbra.Framework.RegisterImportant( nameof( CalculateEffectiveFileList ) + Name,
|
||||
CalculateEffectiveFileListInternal );
|
||||
=> Penumbra.Framework.RegisterImportant(nameof(CalculateEffectiveFileList) + Name,
|
||||
CalculateEffectiveFileListInternal);
|
||||
|
||||
private void CalculateEffectiveFileListInternal()
|
||||
{
|
||||
// Skip the empty collection.
|
||||
if( Index == 0 )
|
||||
{
|
||||
if (Index == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
Penumbra.Log.Debug( $"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {AnonymizedName}" );
|
||||
_cache ??= new Cache( this );
|
||||
Penumbra.Log.Debug($"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {AnonymizedName}");
|
||||
_cache ??= new Cache(this);
|
||||
_cache.FullRecalculation();
|
||||
|
||||
Penumbra.Log.Debug( $"[{Thread.CurrentThread.ManagedThreadId}] Recalculation of effective file list for {AnonymizedName} finished." );
|
||||
Penumbra.Log.Debug($"[{Thread.CurrentThread.ManagedThreadId}] Recalculation of effective file list for {AnonymizedName} finished.");
|
||||
}
|
||||
|
||||
public void SetFiles()
|
||||
{
|
||||
if( _cache == null )
|
||||
if (_cache == null)
|
||||
{
|
||||
Penumbra.CharacterUtility.ResetAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
_cache.MetaManipulations.SetFiles();
|
||||
Penumbra.Log.Debug( $"Set CharacterUtility resources for collection {Name}." );
|
||||
Penumbra.Log.Debug($"Set CharacterUtility resources for collection {Name}.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMetaFile( Interop.Structs.CharacterUtility.Index idx )
|
||||
public void SetMetaFile(Interop.Structs.CharacterUtility.Index idx)
|
||||
{
|
||||
if( _cache == null )
|
||||
{
|
||||
Penumbra.CharacterUtility.ResetResource( idx );
|
||||
}
|
||||
if (_cache == null)
|
||||
Penumbra.CharacterUtility.ResetResource(idx);
|
||||
else
|
||||
{
|
||||
_cache.MetaManipulations.SetFile( idx );
|
||||
}
|
||||
_cache.MetaManipulations.SetFile(idx);
|
||||
}
|
||||
|
||||
// Used for short periods of changed files.
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetEqdpFile( GenderRace genderRace, bool accessory )
|
||||
=> _cache?.MetaManipulations.TemporarilySetEqdpFile( genderRace, accessory )
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource( Interop.Structs.CharacterUtility.EqdpIdx( genderRace, accessory ) );
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetEqdpFile(GenderRace genderRace, bool accessory)
|
||||
=> _cache?.MetaManipulations.TemporarilySetEqdpFile(genderRace, accessory)
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource(Interop.Structs.CharacterUtility.EqdpIdx(genderRace, accessory));
|
||||
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetEqpFile()
|
||||
=> _cache?.MetaManipulations.TemporarilySetEqpFile()
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource( Interop.Structs.CharacterUtility.Index.Eqp );
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource(Interop.Structs.CharacterUtility.Index.Eqp);
|
||||
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetGmpFile()
|
||||
=> _cache?.MetaManipulations.TemporarilySetGmpFile()
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource( Interop.Structs.CharacterUtility.Index.Gmp );
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource(Interop.Structs.CharacterUtility.Index.Gmp);
|
||||
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetCmpFile()
|
||||
=> _cache?.MetaManipulations.TemporarilySetCmpFile()
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource( Interop.Structs.CharacterUtility.Index.HumanCmp );
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource(Interop.Structs.CharacterUtility.Index.HumanCmp);
|
||||
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetEstFile( EstManipulation.EstType type )
|
||||
=> _cache?.MetaManipulations.TemporarilySetEstFile( type )
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource( ( Interop.Structs.CharacterUtility.Index )type );
|
||||
}
|
||||
public CharacterUtility.List.MetaReverter TemporarilySetEstFile(EstManipulation.EstType type)
|
||||
=> _cache?.MetaManipulations.TemporarilySetEstFile(type)
|
||||
?? Penumbra.CharacterUtility.TemporarilyResetResource((Interop.Structs.CharacterUtility.Index)type);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue