Dalamud/Dalamud/Data/RsvResolver.cs
Asriel Camora 0b9af0e3f4
Update to Lumina 5 (new Excel parsing) (#2022)
* Refactor and upgrade to new excel design

* Obsolete ExcelResolver<T> and use only RowRef<T>

* Better benchmarking for Lumina

* Add custom game-supported RSV provider

* Refactor and move Lazy<T> and nullable/cached row objects to RowRefs

* Convert IRSVProvider to delegate, resolve strings by default

* Split IExcelRow into IExcelSubrow

* Extra lumina documentation

* Minor RSV CS fixes

* Fix UIGlowPayload warning

* Fix rebase

* Update to Lumina 5
2024-10-20 19:59:03 -07:00

51 lines
1.8 KiB
C#

using System.Collections.Generic;
using Dalamud.Hooking;
using Dalamud.Logging.Internal;
using Dalamud.Memory;
using FFXIVClientStructs.FFXIV.Client.LayoutEngine;
using Lumina.Text.ReadOnly;
namespace Dalamud.Data;
/// <summary>
/// Provides functionality for resolving RSV strings.
/// </summary>
internal sealed unsafe class RsvResolver : IDisposable
{
private static readonly ModuleLog Log = new("RsvProvider");
private readonly Hook<LayoutWorld.Delegates.AddRsvString> addRsvStringHook;
/// <summary>
/// Initializes a new instance of the <see cref="RsvResolver"/> class.
/// </summary>
public RsvResolver()
{
this.addRsvStringHook = Hook<LayoutWorld.Delegates.AddRsvString>.FromAddress((nint)LayoutWorld.MemberFunctionPointers.AddRsvString, this.AddRsvStringDetour);
this.addRsvStringHook.Enable();
}
private Dictionary<ReadOnlySeString, ReadOnlySeString> Lookup { get; } = [];
/// <summary>Attemps to resolve an RSV string.</summary>
/// <inheritdoc cref="Lumina.Excel.ExcelModule.ResolveRsvDelegate"/>
public bool TryResolve(ReadOnlySeString rsvString, out ReadOnlySeString resolvedString) =>
this.Lookup.TryGetValue(rsvString, out resolvedString);
/// <inheritdoc/>
public void Dispose()
{
this.addRsvStringHook.Dispose();
}
private bool AddRsvStringDetour(LayoutWorld* @this, byte* rsvString, byte* resolvedString, nuint resolvedStringSize)
{
var rsv = new ReadOnlySeString(MemoryHelper.ReadRawNullTerminated((nint)rsvString));
var resolved = new ReadOnlySeString(new ReadOnlySpan<byte>(resolvedString, (int)resolvedStringSize).ToArray());
Log.Debug($"Resolving RSV \"{rsv}\" to \"{resolved}\".");
this.Lookup[rsv] = resolved;
return this.addRsvStringHook.Original(@this, rsvString, resolvedString, resolvedStringSize);
}
}