mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Change subfile handling to maybe retain associated game object for Mare.
This commit is contained in:
parent
4df9ac4632
commit
87b6fe6aa6
5 changed files with 31 additions and 46 deletions
|
|
@ -246,7 +246,7 @@ public unsafe partial class ResourceLoader
|
|||
private static void LogResource( Structs.ResourceHandle* handle, Utf8GamePath path, FullPath? manipulatedPath, ResolveData _ )
|
||||
{
|
||||
var pathString = manipulatedPath != null ? $"custom file {manipulatedPath} instead of {path}" : path.ToString();
|
||||
Penumbra.Log.Information( $"[ResourceLoader] Loaded {pathString} to 0x{( ulong )handle:X}. (Refcount {handle->RefCount})" );
|
||||
Penumbra.Log.Information( $"[ResourceLoader] [{handle->FileType}] Loaded {pathString} to 0x{( ulong )handle:X}. (Refcount {handle->RefCount})" );
|
||||
}
|
||||
|
||||
private static void LogLoadedFile( ByteString path, bool success, bool custom )
|
||||
|
|
|
|||
|
|
@ -45,21 +45,7 @@ public unsafe partial class PathResolver
|
|||
break;
|
||||
case ResourceType.Tmb:
|
||||
case ResourceType.Pap:
|
||||
if( _animationLoadData.Valid )
|
||||
{
|
||||
resolveData = _animationLoadData;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case ResourceType.Avfx:
|
||||
if( _animationLoadData.Valid )
|
||||
{
|
||||
resolveData = _animationLoadData;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case ResourceType.Atex:
|
||||
if( _animationLoadData.Valid )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.Interop.Loader;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.String;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
@ -17,15 +19,18 @@ public unsafe partial class PathResolver
|
|||
// Thus, we need to ensure the correct files are loaded when a material is loaded.
|
||||
public class SubfileHelper : IDisposable
|
||||
{
|
||||
private readonly PathState _paths;
|
||||
private readonly ResourceLoader _loader;
|
||||
|
||||
private ResolveData _mtrlData = ResolveData.Invalid;
|
||||
private ResolveData _avfxData = ResolveData.Invalid;
|
||||
|
||||
public SubfileHelper( PathState paths )
|
||||
private readonly ConcurrentDictionary< IntPtr, ResolveData > _subFileCollection = new();
|
||||
|
||||
public SubfileHelper( ResourceLoader loader )
|
||||
{
|
||||
SignatureHelper.Initialise( this );
|
||||
_paths = paths;
|
||||
|
||||
_loader = loader;
|
||||
}
|
||||
|
||||
// Check specifically for shpk and tex files whether we are currently in a material load.
|
||||
|
|
@ -52,7 +57,7 @@ public unsafe partial class PathResolver
|
|||
}
|
||||
|
||||
// Materials need to be set per collection so they can load their textures independently from each other.
|
||||
public static void HandleCollection( ResolveData resolveData, string path, bool nonDefault, ResourceType type, FullPath? resolved,
|
||||
public static void HandleCollection( ResolveData resolveData, ByteString path, bool nonDefault, ResourceType type, FullPath? resolved,
|
||||
out (FullPath?, ResolveData) data )
|
||||
{
|
||||
if( nonDefault )
|
||||
|
|
@ -75,7 +80,8 @@ public unsafe partial class PathResolver
|
|||
_loadMtrlShpkHook.Enable();
|
||||
_loadMtrlTexHook.Enable();
|
||||
_apricotResourceLoadHook.Enable();
|
||||
Penumbra.ResourceLoader.ResourceLoadCustomization += SubfileLoadHandler;
|
||||
_loader.ResourceLoadCustomization += SubfileLoadHandler;
|
||||
_loader.ResourceLoaded += SubfileContainerLoaded;
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
|
|
@ -83,7 +89,8 @@ public unsafe partial class PathResolver
|
|||
_loadMtrlShpkHook.Disable();
|
||||
_loadMtrlTexHook.Disable();
|
||||
_apricotResourceLoadHook.Disable();
|
||||
Penumbra.ResourceLoader.ResourceLoadCustomization -= SubfileLoadHandler;
|
||||
_loader.ResourceLoadCustomization -= SubfileLoadHandler;
|
||||
_loader.ResourceLoaded -= SubfileContainerLoaded;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -94,6 +101,17 @@ public unsafe partial class PathResolver
|
|||
_apricotResourceLoadHook.Dispose();
|
||||
}
|
||||
|
||||
private void SubfileContainerLoaded( ResourceHandle* handle, Utf8GamePath originalPath, FullPath? manipulatedPath, ResolveData resolveData )
|
||||
{
|
||||
switch( handle->FileType )
|
||||
{
|
||||
case ResourceType.Mtrl:
|
||||
case ResourceType.Avfx:
|
||||
_subFileCollection[ ( IntPtr )handle ] = resolveData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to set the correct collection for the actual material path that is loaded
|
||||
// before actually loading the file.
|
||||
public bool SubfileLoadHandler( ByteString split, ByteString path, ResourceManager* resourceManager,
|
||||
|
|
@ -108,29 +126,12 @@ public unsafe partial class PathResolver
|
|||
default: return false;
|
||||
}
|
||||
|
||||
var lastUnderscore = split.LastIndexOf( ( byte )'_' );
|
||||
var name = lastUnderscore == -1 ? split.ToString() : split.Substring( 0, lastUnderscore ).ToString();
|
||||
if( Penumbra.TempMods.CollectionByName( name, out var collection )
|
||||
|| Penumbra.CollectionManager.ByName( name, out collection ) )
|
||||
{
|
||||
#if DEBUG
|
||||
Penumbra.Log.Verbose( $"Using {nameof(SubfileLoadHandler)} with collection {name} for path {path}." );
|
||||
#endif
|
||||
_paths.SetCollection( IntPtr.Zero, path, collection );
|
||||
}
|
||||
else
|
||||
{
|
||||
#if DEBUG
|
||||
Penumbra.Log.Verbose( $"Using {nameof( SubfileLoadHandler )} with no collection for path {path}." );
|
||||
#endif
|
||||
}
|
||||
|
||||
// Force isSync = true for this call. I don't really understand why,
|
||||
// or where the difference even comes from.
|
||||
// Was called with True on my client and with false on other peoples clients,
|
||||
// which caused problems.
|
||||
ret = Penumbra.ResourceLoader.DefaultLoadResource( path, resourceManager, fileDescriptor, priority, true );
|
||||
_paths.Consume( path, out _ );
|
||||
_subFileCollection.TryRemove( ( IntPtr )fileDescriptor->ResourceHandle, out _ );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -166,16 +167,14 @@ public unsafe partial class PathResolver
|
|||
return ResolveData.Invalid;
|
||||
}
|
||||
|
||||
var resource = ( ResourceHandle* )resourceHandle;
|
||||
var filePath = ByteString.FromSpanUnsafe( resource->FileNameSpan(), true, null, true );
|
||||
return _paths.TryGetValue( filePath, out var c ) ? c : ResolveData.Invalid;
|
||||
return _subFileCollection.TryGetValue( resourceHandle, out var c ) ? c : ResolveData.Invalid;
|
||||
}
|
||||
|
||||
|
||||
private delegate byte ApricotResourceLoadDelegate( IntPtr handle, IntPtr unk1, byte unk2 );
|
||||
|
||||
[Signature( "48 89 74 24 ?? 57 48 83 EC ?? 41 0F B6 F0 48 8B F9", DetourName = nameof( ApricotResourceLoadDetour ) )]
|
||||
private readonly Hook<ApricotResourceLoadDelegate> _apricotResourceLoadHook = null!;
|
||||
private readonly Hook< ApricotResourceLoadDelegate > _apricotResourceLoadHook = null!;
|
||||
|
||||
|
||||
private byte ApricotResourceLoadDetour( IntPtr handle, IntPtr unk1, byte unk2 )
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public partial class PathResolver : IDisposable
|
|||
_animations = new AnimationState( DrawObjects );
|
||||
_paths = new PathState( this );
|
||||
_meta = new MetaState( _paths.HumanVTable );
|
||||
_subFiles = new SubfileHelper( _paths );
|
||||
_subFiles = new SubfileHelper( _loader );
|
||||
}
|
||||
|
||||
// The modified resolver that handles game path resolving.
|
||||
|
|
@ -69,7 +69,7 @@ public partial class PathResolver : IDisposable
|
|||
// Since mtrl files load their files separately, we need to add the new, resolved path
|
||||
// so that the functions loading tex and shpk can find that path and use its collection.
|
||||
// We also need to handle defaulted materials against a non-default collection.
|
||||
var path = resolved == null ? gamePath.Path.ToString() : resolved.Value.FullName;
|
||||
var path = resolved == null ? gamePath.Path : resolved.Value.InternalName;
|
||||
SubfileHelper.HandleCollection( resolveData, path, nonDefault, type, resolved, out data );
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue