mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
ClientStructs-ify some stuff
This commit is contained in:
parent
b5a71ed7b3
commit
c2e5499aef
7 changed files with 53 additions and 110 deletions
|
|
@ -7,7 +7,7 @@ using Penumbra.Meta.Files;
|
|||
using Penumbra.Meta.Manipulations;
|
||||
using Penumbra.String;
|
||||
using Penumbra.String.Classes;
|
||||
using static Penumbra.Interop.Structs.CharacterBaseUtility;
|
||||
using static Penumbra.Interop.Structs.StructExtensions;
|
||||
using ModelType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase.ModelType;
|
||||
|
||||
namespace Penumbra.Interop.ResourceTree;
|
||||
|
|
@ -71,7 +71,7 @@ internal partial record ResolveContext
|
|||
|
||||
private unsafe Utf8GamePath ResolveModelPathNative()
|
||||
{
|
||||
var path = ResolveMdlPath(CharacterBase, SlotIndex);
|
||||
var path = CharacterBase.Value->ResolveMdlPathAsByteString(SlotIndex);
|
||||
return Utf8GamePath.FromByteString(path, out var gamePath) ? gamePath : Utf8GamePath.Empty;
|
||||
}
|
||||
|
||||
|
|
@ -139,8 +139,7 @@ internal partial record ResolveContext
|
|||
|
||||
private unsafe Utf8GamePath ResolveMonsterMaterialPath(Utf8GamePath modelPath, ResourceHandle* imc, byte* mtrlFileName)
|
||||
{
|
||||
// TODO: Submit this (Monster->Variant) to ClientStructs
|
||||
var variant = ResolveMaterialVariant(imc, ((byte*)CharacterBase.Value)[0x8F4]);
|
||||
var variant = ResolveMaterialVariant(imc, (byte)((Monster*)CharacterBase.Value)->Variant);
|
||||
var fileName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(mtrlFileName);
|
||||
|
||||
Span<byte> pathBuffer = stackalloc byte[260];
|
||||
|
|
@ -196,7 +195,7 @@ internal partial record ResolveContext
|
|||
ByteString? path;
|
||||
try
|
||||
{
|
||||
path = ResolveMtrlPath(CharacterBase, SlotIndex, mtrlFileName);
|
||||
path = CharacterBase.Value->ResolveMtrlPathAsByteString(SlotIndex, mtrlFileName);
|
||||
}
|
||||
catch (AccessViolationException)
|
||||
{
|
||||
|
|
@ -277,7 +276,7 @@ internal partial record ResolveContext
|
|||
|
||||
private unsafe Utf8GamePath ResolveSkeletonPathNative(uint partialSkeletonIndex)
|
||||
{
|
||||
var path = ResolveSklbPath(CharacterBase, partialSkeletonIndex);
|
||||
var path = CharacterBase.Value->ResolveSklbPathAsByteString(partialSkeletonIndex);
|
||||
return Utf8GamePath.FromByteString(path, out var gamePath) ? gamePath : Utf8GamePath.Empty;
|
||||
}
|
||||
|
||||
|
|
@ -305,7 +304,7 @@ internal partial record ResolveContext
|
|||
|
||||
private unsafe Utf8GamePath ResolveSkeletonParameterPathNative(uint partialSkeletonIndex)
|
||||
{
|
||||
var path = ResolveSkpPath(CharacterBase, partialSkeletonIndex);
|
||||
var path = CharacterBase.Value->ResolveSkpPathAsByteString(partialSkeletonIndex);
|
||||
return Utf8GamePath.FromByteString(path, out var gamePath) ? gamePath : Utf8GamePath.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ using Penumbra.GameData.Structs;
|
|||
using Penumbra.String;
|
||||
using Penumbra.String.Classes;
|
||||
using Penumbra.UI;
|
||||
using static Penumbra.Interop.Structs.CharacterBaseUtility;
|
||||
using static Penumbra.Interop.Structs.ModelResourceHandleUtility;
|
||||
using static Penumbra.Interop.Structs.StructExtensions;
|
||||
using ModelType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase.ModelType;
|
||||
|
||||
|
|
@ -126,7 +124,7 @@ internal partial record ResolveContext(
|
|||
if (eid == null)
|
||||
return null;
|
||||
|
||||
if (!Utf8GamePath.FromByteString(ResolveEidPath(CharacterBase), out var path))
|
||||
if (!Utf8GamePath.FromByteString(CharacterBase.Value->ResolveEidPathAsByteString(), out var path))
|
||||
return null;
|
||||
|
||||
return GetOrCreateNode(ResourceType.Eid, 0, eid, path);
|
||||
|
|
@ -137,7 +135,7 @@ internal partial record ResolveContext(
|
|||
if (imc == null)
|
||||
return null;
|
||||
|
||||
if (!Utf8GamePath.FromByteString(ResolveImcPath(CharacterBase, SlotIndex), out var path))
|
||||
if (!Utf8GamePath.FromByteString(CharacterBase.Value->ResolveImcPathAsByteString(SlotIndex), out var path))
|
||||
return null;
|
||||
|
||||
return GetOrCreateNode(ResourceType.Imc, 0, imc, path);
|
||||
|
|
@ -174,7 +172,7 @@ internal partial record ResolveContext(
|
|||
if (mtrl == null)
|
||||
continue;
|
||||
|
||||
var mtrlFileName = GetMaterialFileNameBySlot(mdlResource, (uint)i);
|
||||
var mtrlFileName = mdlResource->GetMaterialFileNameBySlot((uint)i);
|
||||
var mtrlNode = CreateNodeFromMaterial(mtrl, ResolveMaterialPath(path, imc, mtrlFileName));
|
||||
if (mtrlNode != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Penumbra.String;
|
||||
|
||||
namespace Penumbra.Interop.Structs;
|
||||
|
||||
// TODO submit these to ClientStructs
|
||||
public static unsafe class CharacterBaseUtility
|
||||
{
|
||||
private const int PathBufferSize = 260;
|
||||
|
||||
private const uint ResolveSklbPathVf = 72;
|
||||
private const uint ResolveMdlPathVf = 73;
|
||||
private const uint ResolveSkpPathVf = 74;
|
||||
private const uint ResolveImcPathVf = 81;
|
||||
private const uint ResolveMtrlPathVf = 82;
|
||||
private const uint ResolveEidPathVf = 85;
|
||||
|
||||
private static void* GetVFunc(CharacterBase* characterBase, uint vfIndex)
|
||||
=> ((void**)characterBase->VTable)[vfIndex];
|
||||
|
||||
private static ByteString? ResolvePath(CharacterBase* characterBase, uint vfIndex)
|
||||
{
|
||||
var vFunc = (delegate* unmanaged<CharacterBase*, byte*, nint, byte*>)GetVFunc(characterBase, vfIndex);
|
||||
var pathBuffer = stackalloc byte[PathBufferSize];
|
||||
var path = vFunc(characterBase, pathBuffer, PathBufferSize);
|
||||
return path != null ? new ByteString(path).Clone() : null;
|
||||
}
|
||||
|
||||
private static ByteString? ResolvePath(CharacterBase* characterBase, uint vfIndex, uint slotIndex)
|
||||
{
|
||||
var vFunc = (delegate* unmanaged<CharacterBase*, byte*, nint, uint, byte*>)GetVFunc(characterBase, vfIndex);
|
||||
var pathBuffer = stackalloc byte[PathBufferSize];
|
||||
var path = vFunc(characterBase, pathBuffer, PathBufferSize, slotIndex);
|
||||
return path != null ? new ByteString(path).Clone() : null;
|
||||
}
|
||||
|
||||
private static ByteString? ResolvePath(CharacterBase* characterBase, uint vfIndex, uint slotIndex, byte* name)
|
||||
{
|
||||
var vFunc = (delegate* unmanaged<CharacterBase*, byte*, nint, uint, byte*, byte*>)GetVFunc(characterBase, vfIndex);
|
||||
var pathBuffer = stackalloc byte[PathBufferSize];
|
||||
var path = vFunc(characterBase, pathBuffer, PathBufferSize, slotIndex, name);
|
||||
return path != null ? new ByteString(path).Clone() : null;
|
||||
}
|
||||
|
||||
public static ByteString? ResolveEidPath(CharacterBase* characterBase)
|
||||
=> ResolvePath(characterBase, ResolveEidPathVf);
|
||||
|
||||
public static ByteString? ResolveImcPath(CharacterBase* characterBase, uint slotIndex)
|
||||
=> ResolvePath(characterBase, ResolveImcPathVf, slotIndex);
|
||||
|
||||
public static ByteString? ResolveMdlPath(CharacterBase* characterBase, uint slotIndex)
|
||||
=> ResolvePath(characterBase, ResolveMdlPathVf, slotIndex);
|
||||
|
||||
public static ByteString? ResolveMtrlPath(CharacterBase* characterBase, uint slotIndex, byte* mtrlFileName)
|
||||
=> ResolvePath(characterBase, ResolveMtrlPathVf, slotIndex, mtrlFileName);
|
||||
|
||||
public static ByteString? ResolveSklbPath(CharacterBase* characterBase, uint partialSkeletonIndex)
|
||||
=> ResolvePath(characterBase, ResolveSklbPathVf, partialSkeletonIndex);
|
||||
|
||||
public static ByteString? ResolveSkpPath(CharacterBase* characterBase, uint partialSkeletonIndex)
|
||||
=> ResolvePath(characterBase, ResolveSkpPathVf, partialSkeletonIndex);
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
|
||||
using Penumbra.GameData;
|
||||
|
||||
namespace Penumbra.Interop.Structs;
|
||||
|
||||
// TODO submit this to ClientStructs
|
||||
public class ModelResourceHandleUtility
|
||||
{
|
||||
public ModelResourceHandleUtility(IGameInteropProvider interop)
|
||||
=> interop.InitializeFromAttributes(this);
|
||||
|
||||
[Signature(Sigs.GetMaterialFileNameBySlot)]
|
||||
private static nint _getMaterialFileNameBySlot = nint.Zero;
|
||||
|
||||
public static unsafe byte* GetMaterialFileNameBySlot(ModelResourceHandle* handle, uint slot)
|
||||
=> ((delegate* unmanaged<ModelResourceHandle*, uint, byte*>)_getMaterialFileNameBySlot)(handle, slot);
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using FFXIVClientStructs.STD;
|
||||
using Penumbra.String;
|
||||
|
||||
|
|
@ -5,20 +6,48 @@ namespace Penumbra.Interop.Structs;
|
|||
|
||||
internal static class StructExtensions
|
||||
{
|
||||
// TODO submit this to ClientStructs
|
||||
public static unsafe ReadOnlySpan<byte> AsSpan(in this StdString str)
|
||||
{
|
||||
if (str.Length < 16)
|
||||
{
|
||||
fixed (StdString* pStr = &str)
|
||||
{
|
||||
return new(pStr->Buffer, (int)str.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
return new(str.BufferPtr, (int)str.Length);
|
||||
}
|
||||
|
||||
public static unsafe ByteString AsByteString(in this StdString str)
|
||||
=> ByteString.FromSpanUnsafe(str.AsSpan(), true);
|
||||
|
||||
public static ByteString ResolveEidPathAsByteString(in this CharacterBase character)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveEidPath(pathBuffer));
|
||||
}
|
||||
|
||||
public static ByteString ResolveImcPathAsByteString(in this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveImcPath(pathBuffer, slotIndex));
|
||||
}
|
||||
|
||||
public static ByteString ResolveMdlPathAsByteString(in this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveMdlPath(pathBuffer, slotIndex));
|
||||
}
|
||||
|
||||
public static unsafe ByteString ResolveMtrlPathAsByteString(in this CharacterBase character, uint slotIndex, byte* mtrlFileName)
|
||||
{
|
||||
var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveMtrlPath(pathBuffer, CharacterBase.PathBufferSize, slotIndex, mtrlFileName));
|
||||
}
|
||||
|
||||
public static ByteString ResolveSklbPathAsByteString(in this CharacterBase character, uint partialSkeletonIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveSklbPath(pathBuffer, partialSkeletonIndex));
|
||||
}
|
||||
|
||||
public static ByteString ResolveSkpPathAsByteString(in this CharacterBase character, uint partialSkeletonIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveSkpPath(pathBuffer, partialSkeletonIndex));
|
||||
}
|
||||
|
||||
private static unsafe ByteString ToOwnedByteString(byte* str)
|
||||
=> str == null ? ByteString.Empty : new ByteString(str).Clone();
|
||||
|
||||
private static ByteString ToOwnedByteString(ReadOnlySpan<byte> str)
|
||||
=> str.Length == 0 ? ByteString.Empty : ByteString.FromSpanUnsafe(str, true).Clone();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ public class Penumbra : IDalamudPlugin
|
|||
_communicatorService = _services.GetService<CommunicatorService>();
|
||||
_services.GetService<ResourceService>(); // Initialize because not required anywhere else.
|
||||
_services.GetService<ModCacheManager>(); // Initialize because not required anywhere else.
|
||||
_services.GetService<ModelResourceHandleUtility>(); // Initialize because not required anywhere else.
|
||||
_collectionManager.Caches.CreateNecessaryCaches();
|
||||
_services.GetService<PathResolver>();
|
||||
_services.GetService<SkinFixer>();
|
||||
|
|
|
|||
|
|
@ -99,8 +99,7 @@ public static class ServiceManagerA
|
|||
.AddSingleton<CreateFileWHook>()
|
||||
.AddSingleton<ResidentResourceManager>()
|
||||
.AddSingleton<FontReloader>()
|
||||
.AddSingleton<RedrawService>()
|
||||
.AddSingleton<ModelResourceHandleUtility>();
|
||||
.AddSingleton<RedrawService>();
|
||||
|
||||
private static ServiceManager AddConfiguration(this ServiceManager services)
|
||||
=> services.AddSingleton<Configuration>()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue