mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
Actually clear cache and restore imc files.
This commit is contained in:
parent
4030487472
commit
b09a736a85
7 changed files with 50 additions and 15 deletions
|
|
@ -153,6 +153,7 @@ public class TempModManager
|
||||||
if( _collections.Remove( characterName, out var c ) )
|
if( _collections.Remove( characterName, out var c ) )
|
||||||
{
|
{
|
||||||
_mods.Remove( c );
|
_mods.Remove( c );
|
||||||
|
c.ClearCache();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,6 @@ public partial class ModCollection
|
||||||
newCollection.CreateCache();
|
newCollection.CreateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveCache( oldCollectionIdx );
|
|
||||||
switch( collectionType )
|
switch( collectionType )
|
||||||
{
|
{
|
||||||
case CollectionType.Default:
|
case CollectionType.Default:
|
||||||
|
|
@ -110,6 +109,7 @@ public partial class ModCollection
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemoveCache( oldCollectionIdx );
|
||||||
|
|
||||||
UpdateCurrentCollectionInUse();
|
UpdateCurrentCollectionInUse();
|
||||||
CollectionChanged.Invoke( collectionType, this[ oldCollectionIdx ], newCollection, characterName );
|
CollectionChanged.Invoke( collectionType, this[ oldCollectionIdx ], newCollection, characterName );
|
||||||
|
|
@ -136,7 +136,6 @@ public partial class ModCollection
|
||||||
_specialCollections[ ( int )collectionType ] = Empty;
|
_specialCollections[ ( int )collectionType ] = Empty;
|
||||||
CollectionChanged.Invoke( collectionType, null, Empty, null );
|
CollectionChanged.Invoke( collectionType, null, Empty, null );
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a special collection if it exists
|
// Remove a special collection if it exists
|
||||||
|
|
@ -361,7 +360,8 @@ public partial class ModCollection
|
||||||
|
|
||||||
private void RemoveCache( int idx )
|
private void RemoveCache( int idx )
|
||||||
{
|
{
|
||||||
if( idx != Default.Index
|
if( idx != Empty.Index
|
||||||
|
&& idx != Default.Index
|
||||||
&& idx != Current.Index
|
&& idx != Current.Index
|
||||||
&& _specialCollections.All( c => c == null || c.Index != idx )
|
&& _specialCollections.All( c => c == null || c.Index != idx )
|
||||||
&& _characters.Values.All( c => c.Index != idx ) )
|
&& _characters.Values.All( c => c.Index != idx ) )
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public partial class ModCollection
|
||||||
|
|
||||||
|
|
||||||
// Clear the current cache.
|
// Clear the current cache.
|
||||||
private void ClearCache()
|
internal void ClearCache()
|
||||||
{
|
{
|
||||||
_cache?.Dispose();
|
_cache?.Dispose();
|
||||||
_cache = null;
|
_cache = null;
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ public partial class ModCollection
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
MetaManipulations.Dispose();
|
||||||
_collection.ModSettingChanged -= OnModSettingChange;
|
_collection.ModSettingChanged -= OnModSettingChange;
|
||||||
_collection.InheritanceChanged -= OnInheritanceChange;
|
_collection.InheritanceChanged -= OnInheritanceChange;
|
||||||
Penumbra.CharacterUtility.LoadingFinished -= IncrementCounter;
|
Penumbra.CharacterUtility.LoadingFinished -= IncrementCounter;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Memory;
|
using FFXIVClientStructs.FFXIV.Client.System.Memory;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
|
using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Interop;
|
namespace Penumbra.Interop;
|
||||||
|
|
||||||
|
|
@ -28,6 +30,7 @@ public unsafe class MetaFileManager : IDisposable
|
||||||
// We only need this if using any meta file.
|
// We only need this if using any meta file.
|
||||||
[Signature( "E8 ?? ?? ?? ?? 41 B9 ?? ?? ?? ?? 4C 8B C0" )]
|
[Signature( "E8 ?? ?? ?? ?? 41 B9 ?? ?? ?? ?? 4C 8B C0" )]
|
||||||
public IntPtr GetFileSpaceAddress;
|
public IntPtr GetFileSpaceAddress;
|
||||||
|
|
||||||
public IMemorySpace* GetFileSpace()
|
public IMemorySpace* GetFileSpace()
|
||||||
=> ( ( delegate* unmanaged< IMemorySpace* > )GetFileSpaceAddress )();
|
=> ( ( delegate* unmanaged< IMemorySpace* > )GetFileSpaceAddress )();
|
||||||
|
|
||||||
|
|
@ -45,7 +48,8 @@ public unsafe class MetaFileManager : IDisposable
|
||||||
public delegate void ClearResource( ResourceHandle* resource );
|
public delegate void ClearResource( ResourceHandle* resource );
|
||||||
public Hook< ClearResource > ClearDefaultResourceHook = null!;
|
public Hook< ClearResource > ClearDefaultResourceHook = null!;
|
||||||
|
|
||||||
private readonly Dictionary< IntPtr, (IntPtr, int) > _originalImcData = new();
|
private readonly Dictionary< IntPtr, (ImcFile, IntPtr, int) > _originalImcData = new();
|
||||||
|
private readonly Dictionary< ImcFile, IntPtr > _currentUse = new();
|
||||||
|
|
||||||
// We store the original data of loaded IMCs so that we can restore it before they get destroyed,
|
// We store the original data of loaded IMCs so that we can restore it before they get destroyed,
|
||||||
// similar to the other meta files, just with arbitrary destruction.
|
// similar to the other meta files, just with arbitrary destruction.
|
||||||
|
|
@ -53,21 +57,48 @@ public unsafe class MetaFileManager : IDisposable
|
||||||
{
|
{
|
||||||
if( _originalImcData.TryGetValue( ( IntPtr )resource, out var data ) )
|
if( _originalImcData.TryGetValue( ( IntPtr )resource, out var data ) )
|
||||||
{
|
{
|
||||||
PluginLog.Debug( "Restoring data of {$Name:l} (0x{Resource}) to 0x{Data:X} and Length {Length} before deletion.",
|
ClearImcData( resource, data.Item1, data.Item2, data.Item3);
|
||||||
Utf8String.FromSpanUnsafe( resource->FileNameSpan(), true, null, null ), ( ulong )resource, ( ulong )data.Item1, data.Item2 );
|
|
||||||
resource->SetData( data.Item1, data.Item2 );
|
|
||||||
_originalImcData.Remove( ( IntPtr )resource );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearDefaultResourceHook.Original( resource );
|
ClearDefaultResourceHook.Original( resource );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset all files from a given IMC cache if they exist.
|
||||||
|
public void ResetByFile( ImcFile file )
|
||||||
|
{
|
||||||
|
if( !_currentUse.TryGetValue( file, out var resource ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _originalImcData.TryGetValue( resource, out var data ) )
|
||||||
|
{
|
||||||
|
ClearImcData((ResourceHandle*) resource, file, data.Item2, data.Item3 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_currentUse.Remove( file );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear a single IMC resource and reset it to its original data.
|
||||||
|
private void ClearImcData( ResourceHandle* resource, ImcFile file, IntPtr data, int length)
|
||||||
|
{
|
||||||
|
var name = new FullPath( Utf8String.FromSpanUnsafe( resource->FileNameSpan(), true ).ToString() );
|
||||||
|
PluginLog.Debug( "Restoring data of {$Name:l} (0x{Resource}) to 0x{Data:X} and Length {Length} before deletion.", name,
|
||||||
|
( ulong )resource, ( ulong )data, length );
|
||||||
|
resource->SetData( data, length );
|
||||||
|
_originalImcData.Remove( ( IntPtr )resource );
|
||||||
|
_currentUse.Remove( file );
|
||||||
|
}
|
||||||
|
|
||||||
// Called when a new IMC is manipulated to store its data.
|
// Called when a new IMC is manipulated to store its data.
|
||||||
public void AddImcFile( ResourceHandle* resource, IntPtr data, int length )
|
public void AddImcFile( ResourceHandle* resource, ImcFile file, IntPtr data, int length)
|
||||||
{
|
{
|
||||||
PluginLog.Debug( "Storing data 0x{Data:X} of Length {Length} for {$Name:l} (0x{Resource:X}).", ( ulong )data, length,
|
PluginLog.Debug( "Storing data 0x{Data:X} of Length {Length} for {$Name:l} (0x{Resource:X}).", ( ulong )data, length,
|
||||||
Utf8String.FromSpanUnsafe( resource->FileNameSpan(), true, null, null ), ( ulong )resource );
|
Utf8String.FromSpanUnsafe( resource->FileNameSpan(), true, null, null ), ( ulong )resource );
|
||||||
_originalImcData[ ( IntPtr )resource ] = ( data, length );
|
_originalImcData[ ( IntPtr )resource ] = ( file, data, length );
|
||||||
|
_currentUse[ file ] = ( IntPtr )resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the hook at VFunc 25, which is called when default resources (and IMC resources do not overwrite it) destroy their data.
|
// Initialize the hook at VFunc 25, which is called when default resources (and IMC resources do not overwrite it) destroy their data.
|
||||||
|
|
@ -83,12 +114,13 @@ public unsafe class MetaFileManager : IDisposable
|
||||||
ClearDefaultResourceHook.Dispose();
|
ClearDefaultResourceHook.Dispose();
|
||||||
// Restore all IMCs to their default values on dispose.
|
// Restore all IMCs to their default values on dispose.
|
||||||
// This should only be relevant when testing/disabling/reenabling penumbra.
|
// This should only be relevant when testing/disabling/reenabling penumbra.
|
||||||
foreach( var (resourcePtr, (data, length)) in _originalImcData )
|
foreach( var (resourcePtr, (file, data, length)) in _originalImcData )
|
||||||
{
|
{
|
||||||
var resource = ( ResourceHandle* )resourcePtr;
|
var resource = ( ResourceHandle* )resourcePtr;
|
||||||
resource->SetData( data, length );
|
resource->SetData( data, length );
|
||||||
}
|
}
|
||||||
|
|
||||||
_originalImcData.Clear();
|
_originalImcData.Clear();
|
||||||
|
_currentUse.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -229,7 +229,7 @@ public unsafe class ImcFile : MetaBaseFile
|
||||||
resource->SetData( ( IntPtr )Data, Length );
|
resource->SetData( ( IntPtr )Data, Length );
|
||||||
if( firstTime )
|
if( firstTime )
|
||||||
{
|
{
|
||||||
Penumbra.MetaFileManager.AddImcFile( resource, data, length );
|
Penumbra.MetaFileManager.AddImcFile( resource, this, data, length );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||||
using OtterGui.Filesystem;
|
using OtterGui.Filesystem;
|
||||||
|
|
@ -118,9 +119,9 @@ public partial class MetaManager
|
||||||
{
|
{
|
||||||
foreach( var file in _imcFiles.Values )
|
foreach( var file in _imcFiles.Values )
|
||||||
{
|
{
|
||||||
|
Penumbra.MetaFileManager.ResetByFile( file );
|
||||||
file.Dispose();
|
file.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_imcFiles.Clear();
|
_imcFiles.Clear();
|
||||||
_imcManipulations.Clear();
|
_imcManipulations.Clear();
|
||||||
RestoreImcDelegate();
|
RestoreImcDelegate();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue