mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 05:04:15 +01:00
Add Initialized / Disposed IPC, start the rest of the plugin only after obtaining the default meta files,
This commit is contained in:
parent
d15ebddf18
commit
4613461154
3 changed files with 252 additions and 182 deletions
|
|
@ -1,9 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using ImGuiScene;
|
||||
|
||||
namespace Penumbra.Interop;
|
||||
|
||||
|
|
@ -13,15 +11,12 @@ public unsafe class CharacterUtility : IDisposable
|
|||
[Signature( "48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? 00 48 8D 8E ?? ?? 00 00 E8 ?? ?? ?? 00 33 D2", ScanType = ScanType.StaticAddress )]
|
||||
private readonly Structs.CharacterUtility** _characterUtilityAddress = null;
|
||||
|
||||
// The initial function in which all the character resources get loaded.
|
||||
public delegate void LoadDataFilesDelegate( Structs.CharacterUtility* characterUtility );
|
||||
|
||||
[Signature( "E8 ?? ?? ?? 00 48 8D 8E ?? ?? 00 00 E8 ?? ?? ?? 00 33 D2", DetourName = "LoadDataFilesDetour")]
|
||||
public Hook< LoadDataFilesDelegate > LoadDataFilesHook = null!;
|
||||
|
||||
public Structs.CharacterUtility* Address
|
||||
=> *_characterUtilityAddress;
|
||||
|
||||
public bool Ready { get; private set; }
|
||||
public event Action LoadingFinished;
|
||||
|
||||
// The relevant indices depend on which meta manipulations we allow for.
|
||||
// The defines are set in the project configuration.
|
||||
public static readonly int[] RelevantIndices
|
||||
|
|
@ -33,7 +28,8 @@ public unsafe class CharacterUtility : IDisposable
|
|||
.Append( Structs.CharacterUtility.GmpIdx )
|
||||
#endif
|
||||
#if USE_EQDP
|
||||
.Concat( Enumerable.Range( Structs.CharacterUtility.EqdpStartIdx, Structs.CharacterUtility.NumEqdpFiles ).Where( i => i != 17 ) ) // TODO: Female Hrothgar
|
||||
.Concat( Enumerable.Range( Structs.CharacterUtility.EqdpStartIdx, Structs.CharacterUtility.NumEqdpFiles )
|
||||
.Where( i => i != 17 ) ) // TODO: Female Hrothgar
|
||||
#endif
|
||||
#if USE_CMP
|
||||
.Append( Structs.CharacterUtility.HumanCmpIdx )
|
||||
|
|
@ -57,38 +53,53 @@ public unsafe class CharacterUtility : IDisposable
|
|||
{
|
||||
SignatureHelper.Initialise( this );
|
||||
|
||||
if( Address->EqpResource != null && Address->EqpResource->Data != null )
|
||||
{
|
||||
LoadDefaultResources();
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadDataFilesHook.Enable();
|
||||
}
|
||||
}
|
||||
|
||||
// Self-disabling hook to set default resources after loading them.
|
||||
private void LoadDataFilesDetour( Structs.CharacterUtility* characterUtility )
|
||||
{
|
||||
LoadDataFilesHook.Original( characterUtility );
|
||||
LoadDefaultResources();
|
||||
PluginLog.Debug( "Character Utility resources loaded and defaults stored, disabling hook." );
|
||||
LoadDataFilesHook.Disable();
|
||||
Dalamud.Framework.Update += LoadDefaultResources;
|
||||
LoadingFinished += () => PluginLog.Debug( "Loading of CharacterUtility finished." );
|
||||
}
|
||||
|
||||
// We store the default data of the resources so we can always restore them.
|
||||
private void LoadDefaultResources()
|
||||
private void LoadDefaultResources( object _ )
|
||||
{
|
||||
var missingCount = 0;
|
||||
if( Address == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for( var i = 0; i < RelevantIndices.Length; ++i )
|
||||
{
|
||||
var resource = ( Structs.ResourceHandle* )Address->Resources[ RelevantIndices[ i ] ];
|
||||
DefaultResources[ i ] = resource->GetData();
|
||||
if( DefaultResources[ i ].Size == 0 )
|
||||
{
|
||||
var resource = ( Structs.ResourceHandle* )Address->Resources[ RelevantIndices[ i ] ];
|
||||
var data = resource->GetData();
|
||||
if( data.Data != IntPtr.Zero && data.Length != 0 )
|
||||
{
|
||||
DefaultResources[ i ] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
++missingCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( missingCount == 0 )
|
||||
{
|
||||
Dalamud.Framework.Update -= LoadDefaultResources;
|
||||
Ready = true;
|
||||
LoadingFinished.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the data of one of the stored resources to a given pointer and length.
|
||||
public bool SetResource( int resourceIdx, IntPtr data, int length )
|
||||
{
|
||||
if( !Ready )
|
||||
{
|
||||
PluginLog.Error( $"Can not set resource {resourceIdx}: CharacterUtility not ready yet." );
|
||||
return false;
|
||||
}
|
||||
|
||||
var resource = Address->Resource( resourceIdx );
|
||||
var ret = resource->SetData( data, length );
|
||||
PluginLog.Verbose( "Set resource {Idx} to 0x{NewData:X} ({NewLength} bytes).", resourceIdx, ( ulong )data, length );
|
||||
|
|
@ -98,6 +109,12 @@ public unsafe class CharacterUtility : IDisposable
|
|||
// Reset the data of one of the stored resources to its default values.
|
||||
public void ResetResource( int resourceIdx )
|
||||
{
|
||||
if( !Ready )
|
||||
{
|
||||
PluginLog.Error( $"Can not reset {resourceIdx}: CharacterUtility not ready yet." );
|
||||
return;
|
||||
}
|
||||
|
||||
var relevantIdx = ReverseIndices[ resourceIdx ];
|
||||
var (data, length) = DefaultResources[ relevantIdx ];
|
||||
var resource = Address->Resource( resourceIdx );
|
||||
|
|
@ -108,16 +125,22 @@ public unsafe class CharacterUtility : IDisposable
|
|||
// Return all relevant resources to the default resource.
|
||||
public void ResetAll()
|
||||
{
|
||||
if( !Ready )
|
||||
{
|
||||
PluginLog.Error( "Can not reset all resources: CharacterUtility not ready yet." );
|
||||
return;
|
||||
}
|
||||
|
||||
foreach( var idx in RelevantIndices )
|
||||
{
|
||||
ResetResource( idx );
|
||||
}
|
||||
PluginLog.Debug( "Reset all CharacterUtility resources to default." );
|
||||
|
||||
PluginLog.Debug( "Reset all CharacterUtility resources to default." );
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ResetAll();
|
||||
LoadDataFilesHook.Dispose();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue