mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Current state.
This commit is contained in:
parent
431933e9c1
commit
9fb8090781
39 changed files with 186 additions and 139 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
|||
Subproject commit 437ef65c6464c54c8f40196dd2428da901d73aab
|
||||
Subproject commit c2738e1d42974cddbe5a31238c6ed236a831d17d
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 3a97e5aeee3b7375b333c1add5305d0ce80cbf83
|
||||
Subproject commit 066637abe05c659b79d84f52e6db33487498f433
|
||||
|
|
@ -2,8 +2,8 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
|||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using Penumbra.Api;
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Communication;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Meta;
|
||||
using Penumbra.Mods;
|
||||
using Penumbra.Mods.Groups;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.SafeHandles;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public sealed class MtrlShpkLoaded() : EventWrapper<nint, nint, MtrlShpkLoaded.P
|
|||
{
|
||||
public enum Priority
|
||||
{
|
||||
/// <seealso cref="Interop.Services.ShaderReplacementFixer.OnMtrlShpkLoaded"/>
|
||||
/// <seealso cref="Penumbra.Interop.Hooks.PostProcessing.ShaderReplacementFixer.OnMtrlShpkLoaded"/>
|
||||
ShaderReplacementFixer = 0,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
namespace Penumbra.Interop.Hooks;
|
||||
|
||||
namespace Penumbra.Interop.Hooks;
|
||||
|
||||
public static class HookSettings
|
||||
{
|
||||
public const bool MetaEntryHooks = false;
|
||||
public const bool MetaParentHooks = false;
|
||||
public const bool VfxIdentificationHooks = false;
|
||||
}
|
||||
public const bool AllHooks = true;
|
||||
|
||||
public const bool ObjectHooks = false && AllHooks;
|
||||
public const bool ReplacementHooks = true && AllHooks;
|
||||
public const bool ResourceHooks = false && AllHooks;
|
||||
public const bool MetaEntryHooks = false && AllHooks;
|
||||
public const bool MetaParentHooks = false && AllHooks;
|
||||
public const bool VfxIdentificationHooks = false && AllHooks;
|
||||
public const bool PostProcessingHooks = false && AllHooks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public sealed unsafe class CharacterBaseDestructor : EventWrapperPtr<CharacterBa
|
|||
|
||||
public CharacterBaseDestructor(HookManager hooks)
|
||||
: base("Destroy CharacterBase")
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, true);
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, HookSettings.ObjectHooks);
|
||||
|
||||
private readonly Task<Hook<Delegate>> _task;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public sealed unsafe class CharacterDestructor : EventWrapperPtr<Character, Char
|
|||
|
||||
public CharacterDestructor(HookManager hooks)
|
||||
: base("Character Destructor")
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Sigs.CharacterDestructor, Detour, true);
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Sigs.CharacterDestructor, Detour, HookSettings.ObjectHooks);
|
||||
|
||||
private readonly Task<Hook<Delegate>> _task;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public sealed unsafe class CopyCharacter : EventWrapperPtr<Character, Character,
|
|||
|
||||
public CopyCharacter(HookManager hooks)
|
||||
: base("Copy Character")
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, true);
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, HookSettings.ObjectHooks);
|
||||
|
||||
private readonly Task<Hook<Delegate>> _task;
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed unsafe class CreateCharacterBase : EventWrapperPtr<ModelCharaId, C
|
|||
|
||||
public CreateCharacterBase(HookManager hooks)
|
||||
: base("Create CharacterBase")
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, true);
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, HookSettings.ObjectHooks);
|
||||
|
||||
private readonly Task<Hook<Delegate>> _task;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public sealed unsafe class EnableDraw : IHookService
|
|||
public EnableDraw(HookManager hooks, GameState state)
|
||||
{
|
||||
_state = state;
|
||||
_task = hooks.CreateHook<Delegate>("Enable Draw", Sigs.EnableDraw, Detour, true);
|
||||
_task = hooks.CreateHook<Delegate>("Enable Draw", Sigs.EnableDraw, Detour, HookSettings.ObjectHooks);
|
||||
}
|
||||
|
||||
private delegate void Delegate(GameObject* gameObject);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public sealed unsafe class WeaponReload : EventWrapperPtr<DrawDataContainer, Cha
|
|||
|
||||
public WeaponReload(HookManager hooks)
|
||||
: base("Reload Weapon")
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, true);
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Address, Detour, HookSettings.ObjectHooks);
|
||||
|
||||
private readonly Task<Hook<Delegate>> _task;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
|||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.SafeHandles;
|
||||
using Penumbra.String.Classes;
|
||||
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
|
||||
|
||||
namespace Penumbra.Interop.Services;
|
||||
namespace Penumbra.Interop.Hooks.PostProcessing;
|
||||
|
||||
public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredService
|
||||
{
|
||||
|
|
@ -29,17 +30,16 @@ public sealed unsafe class PreBoneDeformerReplacer : IDisposable, IRequiredServi
|
|||
private readonly IFramework _framework;
|
||||
|
||||
public PreBoneDeformerReplacer(CharacterUtility utility, CollectionResolver collectionResolver, ResourceLoader resourceLoader,
|
||||
IGameInteropProvider interop, IFramework framework, CharacterBaseVTables vTables)
|
||||
HookManager hooks, IFramework framework, CharacterBaseVTables vTables)
|
||||
{
|
||||
interop.InitializeFromAttributes(this);
|
||||
_utility = utility;
|
||||
_collectionResolver = collectionResolver;
|
||||
_resourceLoader = resourceLoader;
|
||||
_framework = framework;
|
||||
_humanSetupScalingHook = interop.HookFromAddress<CharacterBaseSetupScalingDelegate>(vTables.HumanVTable[57], SetupScaling);
|
||||
_humanCreateDeformerHook = interop.HookFromAddress<CharacterBaseCreateDeformerDelegate>(vTables.HumanVTable[91], CreateDeformer);
|
||||
_humanSetupScalingHook.Enable();
|
||||
_humanCreateDeformerHook.Enable();
|
||||
_utility = utility;
|
||||
_collectionResolver = collectionResolver;
|
||||
_resourceLoader = resourceLoader;
|
||||
_framework = framework;
|
||||
_humanSetupScalingHook = hooks.CreateHook<CharacterBaseSetupScalingDelegate>("HumanSetupScaling", vTables.HumanVTable[58], SetupScaling,
|
||||
HookSettings.PostProcessingHooks).Result;
|
||||
_humanCreateDeformerHook = hooks.CreateHook<CharacterBaseCreateDeformerDelegate>("HumanCreateDeformer", vTables.HumanVTable[101],
|
||||
CreateDeformer, HookSettings.PostProcessingHooks).Result;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
using Dalamud.Hooking;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
|
|
@ -10,9 +8,11 @@ using Penumbra.Communication;
|
|||
using Penumbra.GameData;
|
||||
using Penumbra.Interop.Hooks.Resources;
|
||||
using Penumbra.Services;
|
||||
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
|
||||
using CSModelRenderer = FFXIVClientStructs.FFXIV.Client.Graphics.Render.ModelRenderer;
|
||||
using ModelRenderer = Penumbra.Interop.Services.ModelRenderer;
|
||||
|
||||
namespace Penumbra.Interop.Services;
|
||||
namespace Penumbra.Interop.Hooks.PostProcessing;
|
||||
|
||||
public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredService
|
||||
{
|
||||
|
|
@ -29,8 +29,7 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
|
|||
|
||||
private readonly Hook<CharacterBaseOnRenderMaterialDelegate> _humanOnRenderMaterialHook;
|
||||
|
||||
[Signature(Sigs.ModelRendererOnRenderMaterial, DetourName = nameof(ModelRendererOnRenderMaterialDetour))]
|
||||
private readonly Hook<ModelRendererOnRenderMaterialDelegate> _modelRendererOnRenderMaterialHook = null!;
|
||||
private readonly Hook<ModelRendererOnRenderMaterialDelegate> _modelRendererOnRenderMaterialHook;
|
||||
|
||||
private readonly ResourceHandleDestructor _resourceHandleDestructor;
|
||||
private readonly CommunicatorService _communicator;
|
||||
|
|
@ -59,19 +58,18 @@ public sealed unsafe class ShaderReplacementFixer : IDisposable, IRequiredServic
|
|||
=> _moddedCharacterGlassShpkCount;
|
||||
|
||||
public ShaderReplacementFixer(ResourceHandleDestructor resourceHandleDestructor, CharacterUtility utility, ModelRenderer modelRenderer,
|
||||
CommunicatorService communicator, IGameInteropProvider interop, CharacterBaseVTables vTables)
|
||||
CommunicatorService communicator, HookManager hooks, CharacterBaseVTables vTables)
|
||||
{
|
||||
interop.InitializeFromAttributes(this);
|
||||
_resourceHandleDestructor = resourceHandleDestructor;
|
||||
_utility = utility;
|
||||
_modelRenderer = modelRenderer;
|
||||
_communicator = communicator;
|
||||
_humanOnRenderMaterialHook =
|
||||
interop.HookFromAddress<CharacterBaseOnRenderMaterialDelegate>(vTables.HumanVTable[62], OnRenderHumanMaterial);
|
||||
_humanOnRenderMaterialHook = hooks.CreateHook<CharacterBaseOnRenderMaterialDelegate>("Human.OnRenderMaterial", vTables.HumanVTable[62],
|
||||
OnRenderHumanMaterial, HookSettings.PostProcessingHooks).Result;
|
||||
_modelRendererOnRenderMaterialHook = hooks.CreateHook<ModelRendererOnRenderMaterialDelegate>("ModelRenderer.OnRenderMaterial",
|
||||
Sigs.ModelRendererOnRenderMaterial, ModelRendererOnRenderMaterialDetour, HookSettings.PostProcessingHooks).Result;
|
||||
_communicator.MtrlShpkLoaded.Subscribe(OnMtrlShpkLoaded, MtrlShpkLoaded.Priority.ShaderReplacementFixer);
|
||||
_resourceHandleDestructor.Subscribe(OnResourceHandleDestructor, ResourceHandleDestructor.Priority.ShaderReplacementFixer);
|
||||
_humanOnRenderMaterialHook.Enable();
|
||||
_modelRendererOnRenderMaterialHook.Enable();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -5,7 +5,7 @@ using Penumbra.String;
|
|||
using Penumbra.String.Classes;
|
||||
using Penumbra.String.Functions;
|
||||
|
||||
namespace Penumbra.Interop.ResourceLoading;
|
||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
/// <summary>
|
||||
/// To allow XIV to load files of arbitrary path length,
|
||||
|
|
@ -19,7 +19,8 @@ public unsafe class CreateFileWHook : IDisposable, IRequiredService
|
|||
public CreateFileWHook(IGameInteropProvider interop)
|
||||
{
|
||||
_createFileWHook = interop.HookFromImport<CreateFileWDelegate>(null, "KERNEL32.dll", "CreateFileW", 0, CreateFileWDetour);
|
||||
_createFileWHook.Enable();
|
||||
if (HookSettings.ReplacementHooks)
|
||||
_createFileWHook.Enable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -6,16 +6,17 @@ using Penumbra.GameData;
|
|||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Util;
|
||||
|
||||
namespace Penumbra.Interop.ResourceLoading;
|
||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
public unsafe class FileReadService : IDisposable, IRequiredService
|
||||
{
|
||||
public FileReadService(PerformanceTracker performance, ResourceManagerService resourceManager, IGameInteropProvider interop)
|
||||
{
|
||||
_resourceManager = resourceManager;
|
||||
_performance = performance;
|
||||
_performance = performance;
|
||||
interop.InitializeFromAttributes(this);
|
||||
_readSqPackHook.Enable();
|
||||
if (HookSettings.ReplacementHooks)
|
||||
_readSqPackHook.Enable();
|
||||
}
|
||||
|
||||
/// <summary> Invoked when a file is supposed to be read from SqPack. </summary>
|
||||
|
|
@ -49,7 +50,7 @@ public unsafe class FileReadService : IDisposable, IRequiredService
|
|||
_readSqPackHook.Dispose();
|
||||
}
|
||||
|
||||
private readonly PerformanceTracker _performance;
|
||||
private readonly PerformanceTracker _performance;
|
||||
private readonly ResourceManagerService _resourceManager;
|
||||
|
||||
private delegate byte ReadSqPackPrototype(nint resourceManager, SeFileDescriptor* pFileDesc, int priority, bool isSync);
|
||||
|
|
@ -60,7 +61,7 @@ public unsafe class FileReadService : IDisposable, IRequiredService
|
|||
private byte ReadSqPackDetour(nint resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync)
|
||||
{
|
||||
using var performance = _performance.Measure(PerformanceType.ReadSqPack);
|
||||
byte? ret = null;
|
||||
byte? ret = null;
|
||||
_lastFileThreadResourceManager.Value = resourceManager;
|
||||
ReadSqPack?.Invoke(fileDescriptor, ref priority, ref isSync, ref ret);
|
||||
_lastFileThreadResourceManager.Value = nint.Zero;
|
||||
|
|
@ -9,27 +9,27 @@ using Penumbra.String;
|
|||
using Penumbra.String.Classes;
|
||||
using FileMode = Penumbra.Interop.Structs.FileMode;
|
||||
|
||||
namespace Penumbra.Interop.ResourceLoading;
|
||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
public unsafe class ResourceLoader : IDisposable, IService
|
||||
{
|
||||
private readonly ResourceService _resources;
|
||||
private readonly FileReadService _fileReadService;
|
||||
private readonly TexMdlService _texMdlService;
|
||||
private readonly TexMdlService _texMdlService;
|
||||
|
||||
private ResolveData _resolvedData = ResolveData.Invalid;
|
||||
|
||||
public ResourceLoader(ResourceService resources, FileReadService fileReadService, TexMdlService texMdlService)
|
||||
{
|
||||
_resources = resources;
|
||||
_resources = resources;
|
||||
_fileReadService = fileReadService;
|
||||
_texMdlService = texMdlService;
|
||||
_texMdlService = texMdlService;
|
||||
ResetResolvePath();
|
||||
|
||||
_resources.ResourceRequested += ResourceHandler;
|
||||
_resources.ResourceRequested += ResourceHandler;
|
||||
_resources.ResourceHandleIncRef += IncRefProtection;
|
||||
_resources.ResourceHandleDecRef += DecRefProtection;
|
||||
_fileReadService.ReadSqPack += ReadSqPackDetour;
|
||||
_fileReadService.ReadSqPack += ReadSqPackDetour;
|
||||
}
|
||||
|
||||
/// <summary> Load a resource for a given path and a specific collection. </summary>
|
||||
|
|
@ -80,10 +80,10 @@ public unsafe class ResourceLoader : IDisposable, IService
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_resources.ResourceRequested -= ResourceHandler;
|
||||
_resources.ResourceRequested -= ResourceHandler;
|
||||
_resources.ResourceHandleIncRef -= IncRefProtection;
|
||||
_resources.ResourceHandleDecRef -= DecRefProtection;
|
||||
_fileReadService.ReadSqPack -= ReadSqPackDetour;
|
||||
_fileReadService.ReadSqPack -= ReadSqPackDetour;
|
||||
}
|
||||
|
||||
private void ResourceHandler(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path,
|
||||
|
|
@ -112,7 +112,7 @@ public unsafe class ResourceLoader : IDisposable, IService
|
|||
// Replace the hash and path with the correct one for the replacement.
|
||||
hash = ComputeHash(resolvedPath.Value.InternalName, parameters);
|
||||
var oldPath = path;
|
||||
path = p;
|
||||
path = p;
|
||||
returnValue = _resources.GetOriginalResource(sync, category, type, hash, path.Path, parameters);
|
||||
ResourceLoaded?.Invoke(returnValue, oldPath, resolvedPath.Value, data);
|
||||
}
|
||||
|
|
@ -140,12 +140,12 @@ public unsafe class ResourceLoader : IDisposable, IService
|
|||
}
|
||||
|
||||
var path = ByteString.FromSpanUnsafe(actualPath, gamePath.Path.IsNullTerminated, gamePath.Path.IsAsciiLowerCase, gamePath.Path.IsAscii);
|
||||
fileDescriptor->ResourceHandle->FileNameData = path.Path;
|
||||
fileDescriptor->ResourceHandle->FileNameData = path.Path;
|
||||
fileDescriptor->ResourceHandle->FileNameLength = path.Length;
|
||||
MtrlForceSync(fileDescriptor, ref isSync);
|
||||
returnValue = DefaultLoadResource(path, fileDescriptor, priority, isSync, data);
|
||||
// Return original resource handle path so that they can be loaded separately.
|
||||
fileDescriptor->ResourceHandle->FileNameData = gamePath.Path.Path;
|
||||
fileDescriptor->ResourceHandle->FileNameData = gamePath.Path.Path;
|
||||
fileDescriptor->ResourceHandle->FileNameLength = gamePath.Path.Length;
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ public unsafe class ResourceLoader : IDisposable, IService
|
|||
// Ensure that the file descriptor has its wchar_t array on aligned boundary even if it has to be odd.
|
||||
var fd = stackalloc char[0x11 + 0x0B + 14];
|
||||
fileDescriptor->FileDescriptor = (byte*)fd + 1;
|
||||
CreateFileWHook.WritePtr(fd + 0x11, gamePath.Path, gamePath.Length);
|
||||
CreateFileWHook.WritePtr(fd + 0x11, gamePath.Path, gamePath.Length);
|
||||
CreateFileWHook.WritePtr(&fileDescriptor->Utf16FileName, gamePath.Path, gamePath.Length);
|
||||
|
||||
// Use the SE ReadFile function.
|
||||
|
|
@ -206,7 +206,7 @@ public unsafe class ResourceLoader : IDisposable, IService
|
|||
return;
|
||||
|
||||
_incMode.Value = true;
|
||||
returnValue = _resources.IncRef(handle);
|
||||
returnValue = _resources.IncRef(handle);
|
||||
_incMode.Value = false;
|
||||
}
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ using OtterGui.Services;
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData;
|
||||
|
||||
namespace Penumbra.Interop.ResourceLoading;
|
||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
public unsafe class ResourceManagerService : IRequiredService
|
||||
{
|
||||
|
|
@ -23,10 +23,10 @@ public unsafe class ResourceManagerService : IRequiredService
|
|||
public ResourceHandle* FindResource(ResourceCategory cat, ResourceType ext, uint crc32)
|
||||
{
|
||||
ref var manager = ref *ResourceManager;
|
||||
var catIdx = (uint)cat >> 0x18;
|
||||
var catIdx = (uint)cat >> 0x18;
|
||||
cat = (ResourceCategory)(ushort)cat;
|
||||
ref var category = ref manager.ResourceGraph->Containers[(int)cat];
|
||||
var extMap = FindInMap(category.CategoryMaps[(int)catIdx].Value, (uint)ext);
|
||||
var extMap = FindInMap(category.CategoryMaps[(int)catIdx].Value, (uint)ext);
|
||||
if (extMap == null)
|
||||
return null;
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ using Penumbra.String.Classes;
|
|||
using Penumbra.Util;
|
||||
using CSResourceHandle = FFXIVClientStructs.FFXIV.Client.System.Resource.Handle.ResourceHandle;
|
||||
|
||||
namespace Penumbra.Interop.ResourceLoading;
|
||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
public unsafe class ResourceService : IDisposable, IRequiredService
|
||||
{
|
||||
|
|
@ -24,16 +24,19 @@ public unsafe class ResourceService : IDisposable, IRequiredService
|
|||
_performance = performance;
|
||||
_resourceManager = resourceManager;
|
||||
interop.InitializeFromAttributes(this);
|
||||
_getResourceSyncHook.Enable();
|
||||
_getResourceAsyncHook.Enable();
|
||||
_incRefHook = interop.HookFromAddress<ResourceHandlePrototype>(
|
||||
(nint)CSResourceHandle.MemberFunctionPointers.IncRef,
|
||||
ResourceHandleIncRefDetour);
|
||||
_incRefHook.Enable();
|
||||
_decRefHook = interop.HookFromAddress<ResourceHandleDecRefPrototype>(
|
||||
(nint)CSResourceHandle.MemberFunctionPointers.DecRef,
|
||||
ResourceHandleDecRefDetour);
|
||||
_decRefHook.Enable();
|
||||
if (HookSettings.ReplacementHooks)
|
||||
{
|
||||
_getResourceSyncHook.Enable();
|
||||
_getResourceAsyncHook.Enable();
|
||||
_incRefHook.Enable();
|
||||
_decRefHook.Enable();
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceHandle* GetResource(ResourceCategory category, ResourceType type, ByteString path)
|
||||
|
|
@ -1,109 +1,138 @@
|
|||
using Dalamud.Hooking;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.LayoutEngine;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
using Lumina.Excel.GeneratedSheets2;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.String.Classes;
|
||||
using FileMode = Penumbra.Interop.Structs.FileMode;
|
||||
using ResourceHandle = FFXIVClientStructs.FFXIV.Client.System.Resource.Handle.ResourceHandle;
|
||||
|
||||
namespace Penumbra.Interop.ResourceLoading;
|
||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
public unsafe class TexMdlService : IDisposable, IRequiredService
|
||||
{
|
||||
/// <summary> Custom ulong flag to signal our files as opposed to SE files. </summary>
|
||||
public static readonly nint CustomFileFlag = new(0xDEADBEEF);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// We need to keep a list of all CRC64 hash values of our replaced Mdl and Tex files,
|
||||
/// i.e. CRC32 of filename in the lower bytes, CRC32 of parent path in the upper bytes.
|
||||
/// </summary>
|
||||
public IReadOnlySet<ulong> CustomFileCrc
|
||||
=> _customFileCrc;
|
||||
|
||||
|
||||
public TexMdlService(IGameInteropProvider interop)
|
||||
{
|
||||
interop.InitializeFromAttributes(this);
|
||||
//_checkFileStateHook.Enable();
|
||||
//_loadTexFileExternHook.Enable();
|
||||
//_loadMdlFileExternHook.Enable();
|
||||
if (HookSettings.ReplacementHooks)
|
||||
{
|
||||
_checkFileStateHook.Enable();
|
||||
_loadMdlFileExternHook.Enable();
|
||||
_textureSomethingHook.Enable();
|
||||
_vf32Hook.Enable();
|
||||
//_loadTexFileExternHook.Enable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Add CRC64 if the given file is a model or texture file and has an associated path. </summary>
|
||||
public void AddCrc(ResourceType type, FullPath? path)
|
||||
{
|
||||
if (path.HasValue && type is ResourceType.Mdl or ResourceType.Tex)
|
||||
if (path.HasValue && type is ResourceType.Mdl)
|
||||
_customFileCrc.Add(path.Value.Crc64);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Add a fixed CRC64 value. </summary>
|
||||
public void AddCrc(ulong crc64)
|
||||
=> _customFileCrc.Add(crc64);
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
//_checkFileStateHook.Dispose();
|
||||
_checkFileStateHook.Dispose();
|
||||
//_loadTexFileExternHook.Dispose();
|
||||
//_loadMdlFileExternHook.Dispose();
|
||||
_textureSomethingHook.Dispose();
|
||||
_loadMdlFileExternHook.Dispose();
|
||||
_vf32Hook.Dispose();
|
||||
}
|
||||
|
||||
private readonly HashSet<ulong> _customFileCrc = new();
|
||||
|
||||
|
||||
private readonly HashSet<ulong> _customFileCrc = [];
|
||||
|
||||
private delegate nint CheckFileStatePrototype(nint unk1, ulong crc64);
|
||||
|
||||
|
||||
private delegate nint TextureSomethingDelegate(TextureResourceHandle* handle, int lod, SeFileDescriptor* descriptor);
|
||||
|
||||
[Signature(Sigs.CheckFileState, DetourName = nameof(CheckFileStateDetour))]
|
||||
private readonly Hook<CheckFileStatePrototype> _checkFileStateHook = null!;
|
||||
|
||||
|
||||
[Signature("E8 ?? ?? ?? ?? 0F B6 C8 EB ?? 4C 8B 83", DetourName = nameof(TextureSomethingDetour))]
|
||||
private readonly Hook<TextureSomethingDelegate> _textureSomethingHook = null!;
|
||||
|
||||
private nint TextureSomethingDetour(TextureResourceHandle* handle, int lod, SeFileDescriptor* descriptor)
|
||||
{
|
||||
//Penumbra.Log.Information($"SomethingDetour {handle->Handle.FileName()}");
|
||||
//if (!handle->Handle.GamePath(out var path) || !path.IsRooted())
|
||||
return _textureSomethingHook.Original(handle, lod, descriptor);
|
||||
|
||||
descriptor->FileMode = FileMode.LoadUnpackedResource;
|
||||
return _loadTexFileLocal.Invoke((ResourceHandle*)handle, lod, (nint)descriptor, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The function that checks a files CRC64 to determine whether it is 'protected'.
|
||||
/// We use it to check against our stored CRC64s and if it corresponds, we return the custom flag.
|
||||
/// </summary>
|
||||
private nint CheckFileStateDetour(nint ptr, ulong crc64)
|
||||
=> _customFileCrc.Contains(crc64) ? CustomFileFlag : _checkFileStateHook.Original(ptr, crc64);
|
||||
|
||||
|
||||
|
||||
|
||||
private delegate byte LoadTexFileLocalDelegate(ResourceHandle* handle, int unk1, nint unk2, bool unk3);
|
||||
|
||||
|
||||
/// <summary> We use the local functions for our own files in the extern hook. </summary>
|
||||
[Signature(Sigs.LoadTexFileLocal)]
|
||||
private readonly LoadTexFileLocalDelegate _loadTexFileLocal = null!;
|
||||
|
||||
|
||||
private delegate byte LoadMdlFileLocalPrototype(ResourceHandle* handle, nint unk1, bool unk2);
|
||||
|
||||
|
||||
/// <summary> We use the local functions for our own files in the extern hook. </summary>
|
||||
[Signature(Sigs.LoadMdlFileLocal)]
|
||||
private readonly LoadMdlFileLocalPrototype _loadMdlFileLocal = null!;
|
||||
|
||||
|
||||
|
||||
|
||||
private delegate byte LoadTexFileExternPrototype(ResourceHandle* handle, int unk1, nint unk2, bool unk3, nint unk4);
|
||||
|
||||
private delegate byte TexResourceHandleVf32Prototype(TextureResourceHandle* handle, SeFileDescriptor* descriptor, byte unk2);
|
||||
|
||||
[Signature("40 53 55 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B D9", DetourName = nameof(Vf32Detour))]
|
||||
private readonly Hook<TexResourceHandleVf32Prototype> _vf32Hook = null!;
|
||||
|
||||
private delegate byte TexResourceHandleVf32Prototype(ResourceHandle* handle, nint unk1, byte unk2);
|
||||
|
||||
//[Signature("40 53 55 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B D9", DetourName = nameof(Vf32Detour))]
|
||||
//private readonly Hook<TexResourceHandleVf32Prototype> _vf32Hook = null!;
|
||||
//
|
||||
//private byte Vf32Detour(ResourceHandle* handle, nint unk1, byte unk2)
|
||||
//{
|
||||
// var ret = _vf32Hook.Original(handle, unk1, unk2);
|
||||
// return _loadTexFileLocal()
|
||||
//}
|
||||
|
||||
private byte Vf32Detour(TextureResourceHandle* handle, SeFileDescriptor* descriptor, byte unk2)
|
||||
{
|
||||
//if (handle->Handle.GamePath(out var path) && path.IsRooted())
|
||||
//{
|
||||
// Penumbra.Log.Information($"Replacing {descriptor->FileMode} with {FileMode.LoadSqPackResource} in VF32 for {path}.");
|
||||
// descriptor->FileMode = FileMode.LoadSqPackResource;
|
||||
//}
|
||||
|
||||
var ret = _vf32Hook.Original(handle, descriptor, unk2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//[Signature(Sigs.LoadTexFileExtern, DetourName = nameof(LoadTexFileExternDetour))]
|
||||
//private readonly Hook<LoadTexFileExternPrototype> _loadTexFileExternHook = null!;
|
||||
|
||||
|
||||
/// <summary> We hook the extern functions to just return the local one if given the custom flag as last argument. </summary>
|
||||
//private byte LoadTexFileExternDetour(ResourceHandle* resourceHandle, int unk1, nint unk2, bool unk3, nint ptr)
|
||||
// => ptr.Equals(CustomFileFlag)
|
||||
// ? _loadTexFileLocal.Invoke(resourceHandle, unk1, unk2, unk3)
|
||||
// : _loadTexFileExternHook.Original(resourceHandle, unk1, unk2, unk3, ptr);
|
||||
|
||||
public delegate byte LoadMdlFileExternPrototype(ResourceHandle* handle, nint unk1, bool unk2, nint unk3);
|
||||
|
||||
|
||||
|
||||
|
||||
[Signature(Sigs.LoadMdlFileExtern, DetourName = nameof(LoadMdlFileExternDetour))]
|
||||
private readonly Hook<LoadMdlFileExternPrototype> _loadMdlFileExternHook = null!;
|
||||
|
||||
|
||||
/// <summary> We hook the extern functions to just return the local one if given the custom flag as last argument. </summary>
|
||||
private byte LoadMdlFileExternDetour(ResourceHandle* resourceHandle, nint unk1, bool unk2, nint ptr)
|
||||
=> ptr.Equals(CustomFileFlag)
|
||||
|
|
@ -11,7 +11,7 @@ public sealed unsafe class ApricotResourceLoad : FastHook<ApricotResourceLoad.De
|
|||
public ApricotResourceLoad(HookManager hooks, GameState gameState)
|
||||
{
|
||||
_gameState = gameState;
|
||||
Task = hooks.CreateHook<Delegate>("Load Apricot Resource", Sigs.ApricotResourceLoad, Detour, true);
|
||||
Task = hooks.CreateHook<Delegate>("Load Apricot Resource", Sigs.ApricotResourceLoad, Detour, HookSettings.ResourceHooks);
|
||||
}
|
||||
|
||||
public delegate byte Delegate(ResourceHandle* handle, nint unk1, byte unk2);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public sealed unsafe class LoadMtrlShpk : FastHook<LoadMtrlShpk.Delegate>
|
|||
{
|
||||
_gameState = gameState;
|
||||
_communicator = communicator;
|
||||
Task = hooks.CreateHook<Delegate>("Load Material Shaders", Sigs.LoadMtrlShpk, Detour, true);
|
||||
Task = hooks.CreateHook<Delegate>("Load Material Shaders", Sigs.LoadMtrlShpk, Detour, HookSettings.ResourceHooks);
|
||||
}
|
||||
|
||||
public delegate byte Delegate(MaterialResourceHandle* mtrlResourceHandle);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ public sealed unsafe class LoadMtrlTex : FastHook<LoadMtrlTex.Delegate>
|
|||
public LoadMtrlTex(HookManager hooks, GameState gameState)
|
||||
{
|
||||
_gameState = gameState;
|
||||
Task = hooks.CreateHook<Delegate>("Load Material Textures", Sigs.LoadMtrlTex, Detour, true);
|
||||
Task = hooks.CreateHook<Delegate>("Load Material Textures", Sigs.LoadMtrlTex, Detour, HookSettings.ResourceHooks);
|
||||
}
|
||||
|
||||
public delegate byte Delegate(MaterialResourceHandle* mtrlResourceHandle);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
_resolveVfxPathHook = Create<VfxResolveDelegate>( $"{name}.{nameof(ResolveVfx)}", hooks, vTable[93], type, ResolveVfx, ResolveVfxHuman);
|
||||
_resolveEidPathHook = Create<SingleResolveDelegate>( $"{name}.{nameof(ResolveEid)}", hooks, vTable[94], ResolveEid);
|
||||
// @formatter:on
|
||||
Enable();
|
||||
if (HookSettings.ResourceHooks)
|
||||
Enable();
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public sealed unsafe class ResourceHandleDestructor : EventWrapperPtr<ResourceHa
|
|||
|
||||
public ResourceHandleDestructor(HookManager hooks)
|
||||
: base("Destroy ResourceHandle")
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Sigs.ResourceHandleDestructor, Detour, true);
|
||||
=> _task = hooks.CreateHook<Delegate>(Name, Sigs.ResourceHandleDestructor, Detour, HookSettings.ResourceHooks);
|
||||
|
||||
private readonly Task<Hook<Delegate>> _task;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ using OtterGui.Services;
|
|||
using Penumbra.Collections;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Services;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.String.Classes;
|
||||
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
|
||||
using Penumbra.Interop.Hooks.Objects;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
namespace Penumbra.Interop.PathResolving;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ using OtterGui.Services;
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Collections.Manager;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.Processing;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.Util;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.Resources;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Frozen;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.String;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ using Penumbra.Collections;
|
|||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.Hooks.PostProcessing;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Interop.Services;
|
||||
using Penumbra.String;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.UI;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
|||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.Interop.Services;
|
||||
using Penumbra.Interop.Hooks.PostProcessing;
|
||||
using Penumbra.UI;
|
||||
using CustomizeData = FFXIVClientStructs.FFXIV.Client.Game.Character.CustomizeData;
|
||||
using CustomizeIndex = Dalamud.Game.ClientState.Objects.Enums.CustomizeIndex;
|
||||
|
|
@ -31,7 +31,8 @@ public class ResourceTree
|
|||
public CustomizeData CustomizeData;
|
||||
public GenderRace RaceCode;
|
||||
|
||||
public ResourceTree(string name, string anonymizedName, int gameObjectIndex, nint gameObjectAddress, nint drawObjectAddress, bool localPlayerRelated, bool playerRelated, bool networked, string collectionName, string anonymizedCollectionName)
|
||||
public ResourceTree(string name, string anonymizedName, int gameObjectIndex, nint gameObjectAddress, nint drawObjectAddress,
|
||||
bool localPlayerRelated, bool playerRelated, bool networked, string collectionName, string anonymizedCollectionName)
|
||||
{
|
||||
Name = name;
|
||||
AnonymizedName = anonymizedName;
|
||||
|
|
@ -61,9 +62,10 @@ public class ResourceTree
|
|||
var human = modelType == CharacterBase.ModelType.Human ? (Human*)model : null;
|
||||
var equipment = modelType switch
|
||||
{
|
||||
CharacterBase.ModelType.Human => new ReadOnlySpan<CharacterArmor>(&human->Head, 10),
|
||||
CharacterBase.ModelType.DemiHuman => new ReadOnlySpan<CharacterArmor>(Unsafe.AsPointer(ref character->DrawData.EquipmentModelIds[0]), 10),
|
||||
_ => ReadOnlySpan<CharacterArmor>.Empty,
|
||||
CharacterBase.ModelType.Human => new ReadOnlySpan<CharacterArmor>(&human->Head, 10),
|
||||
CharacterBase.ModelType.DemiHuman => new ReadOnlySpan<CharacterArmor>(
|
||||
Unsafe.AsPointer(ref character->DrawData.EquipmentModelIds[0]), 10),
|
||||
_ => ReadOnlySpan<CharacterArmor>.Empty,
|
||||
};
|
||||
ModelId = character->CharacterData.ModelCharaId;
|
||||
CustomizeData = character->DrawData.CustomizeData;
|
||||
|
|
@ -112,15 +114,17 @@ public class ResourceTree
|
|||
{
|
||||
if (baseSubObject->GetObjectType() != FFXIVClientStructs.FFXIV.Client.Graphics.Scene.ObjectType.CharacterBase)
|
||||
continue;
|
||||
|
||||
var subObject = (CharacterBase*)baseSubObject;
|
||||
|
||||
if (subObject->GetModelType() != CharacterBase.ModelType.Weapon)
|
||||
continue;
|
||||
var weapon = (Weapon*)subObject;
|
||||
|
||||
var weapon = (Weapon*)subObject;
|
||||
|
||||
// This way to tell apart MainHand and OffHand is not always accurate, but seems good enough for what we're doing with it.
|
||||
var slot = weaponIndex > 0 ? EquipSlot.OffHand : EquipSlot.MainHand;
|
||||
var equipment = new CharacterArmor(weapon->ModelSetId, (byte)weapon->Variant, (byte)weapon->ModelUnknown);
|
||||
var equipment = new CharacterArmor(weapon->ModelSetId, (byte)weapon->Variant, new StainIds(weapon->Stain1, weapon->Stain2));
|
||||
var weaponType = weapon->SecondaryId;
|
||||
|
||||
var genericContext = globalContext.CreateContext(subObject, 0xFFFFFFFFu, slot, equipment, weaponType);
|
||||
|
|
@ -152,6 +156,7 @@ public class ResourceTree
|
|||
|
||||
++weaponIndex;
|
||||
}
|
||||
|
||||
Nodes.InsertRange(0, weaponNodes);
|
||||
}
|
||||
|
||||
|
|
@ -167,10 +172,11 @@ public class ResourceTree
|
|||
{
|
||||
if (globalContext.WithUiData)
|
||||
{
|
||||
pbdNode = pbdNode.Clone();
|
||||
pbdNode = pbdNode.Clone();
|
||||
pbdNode.FallbackName = "Racial Deformer";
|
||||
pbdNode.Icon = ChangedItemDrawer.ChangedItemIcon.Customization;
|
||||
pbdNode.Icon = ChangedItemDrawer.ChangedItemIcon.Customization;
|
||||
}
|
||||
|
||||
Nodes.Add(pbdNode);
|
||||
}
|
||||
}
|
||||
|
|
@ -184,10 +190,11 @@ public class ResourceTree
|
|||
{
|
||||
if (globalContext.WithUiData)
|
||||
{
|
||||
decalNode = decalNode.Clone();
|
||||
decalNode = decalNode.Clone();
|
||||
decalNode.FallbackName = "Face Decal";
|
||||
decalNode.Icon = ChangedItemDrawer.ChangedItemIcon.Customization;
|
||||
}
|
||||
|
||||
Nodes.Add(decalNode);
|
||||
}
|
||||
|
||||
|
|
@ -200,10 +207,11 @@ public class ResourceTree
|
|||
{
|
||||
if (globalContext.WithUiData)
|
||||
{
|
||||
legacyDecalNode = legacyDecalNode.Clone();
|
||||
legacyDecalNode = legacyDecalNode.Clone();
|
||||
legacyDecalNode.FallbackName = "Legacy Body Decal";
|
||||
legacyDecalNode.Icon = ChangedItemDrawer.ChangedItemIcon.Customization;
|
||||
}
|
||||
|
||||
Nodes.Add(legacyDecalNode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
namespace Penumbra.Interop.Services;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ using Penumbra.Api;
|
|||
using Penumbra.Api.Enums;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.Collections.Cache;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.Interop.Services;
|
||||
|
|
@ -22,6 +21,7 @@ using Penumbra.GameData.Enums;
|
|||
using Penumbra.UI;
|
||||
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
||||
using System.Xml.Linq;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
namespace Penumbra;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
|
||||
<DalamudLibPath>H:\Projects\FFPlugins\Dalamud\bin\Release\</DalamudLibPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using Penumbra.Communication;
|
|||
using Penumbra.CrashHandler;
|
||||
using Penumbra.CrashHandler.Buffers;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.String;
|
||||
using Penumbra.String.Classes;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ using Penumbra.Api.Enums;
|
|||
using Penumbra.Collections;
|
||||
using Penumbra.GameData.Actors;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.Resources;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Services;
|
||||
using Penumbra.String;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ using Penumbra.GameData.Interop;
|
|||
using Penumbra.Import.Structs;
|
||||
using Penumbra.Import.Textures;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Services;
|
||||
using Penumbra.Interop.Structs;
|
||||
using Penumbra.Mods;
|
||||
|
|
@ -40,6 +39,8 @@ using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
|
|||
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
||||
using ImGuiClip = OtterGui.ImGuiClip;
|
||||
using Penumbra.Api.IpcTester;
|
||||
using Penumbra.Interop.Hooks.PostProcessing;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
|
||||
namespace Penumbra.UI.Tabs.Debug;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using OtterGui.Services;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.Interop.ResourceLoading;
|
||||
using Penumbra.Interop.Hooks.ResourceLoading;
|
||||
using Penumbra.String.Classes;
|
||||
|
||||
namespace Penumbra.UI.Tabs;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue