mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-02-17 21:37:43 +01:00
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
This commit is contained in:
parent
08d8605871
commit
0b9af0e3f4
49 changed files with 460 additions and 403 deletions
|
|
@ -11,6 +11,7 @@ using Dalamud.Utility.Timing;
|
|||
using Lumina;
|
||||
using Lumina.Data;
|
||||
using Lumina.Excel;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
|
||||
|
|
@ -28,12 +29,15 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
|
|||
{
|
||||
private readonly Thread luminaResourceThread;
|
||||
private readonly CancellationTokenSource luminaCancellationTokenSource;
|
||||
private readonly RsvResolver rsvResolver;
|
||||
|
||||
[ServiceManager.ServiceConstructor]
|
||||
private DataManager(Dalamud dalamud)
|
||||
{
|
||||
this.Language = (ClientLanguage)dalamud.StartInfo.Language;
|
||||
|
||||
this.rsvResolver = new();
|
||||
|
||||
try
|
||||
{
|
||||
Log.Verbose("Starting data load...");
|
||||
|
|
@ -44,11 +48,8 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
|
|||
{
|
||||
LoadMultithreaded = true,
|
||||
CacheFileResources = true,
|
||||
#if NEVER // Lumina bug
|
||||
PanicOnSheetChecksumMismatch = true,
|
||||
#else
|
||||
PanicOnSheetChecksumMismatch = false,
|
||||
#endif
|
||||
RsvResolver = this.rsvResolver.TryResolve,
|
||||
DefaultExcelLanguage = this.Language.ToLumina(),
|
||||
};
|
||||
|
||||
|
|
@ -129,12 +130,12 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
|
|||
#region Lumina Wrappers
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ExcelSheet<T>? GetExcelSheet<T>() where T : ExcelRow
|
||||
=> this.Excel.GetSheet<T>();
|
||||
public ExcelSheet<T> GetExcelSheet<T>(ClientLanguage? language = null, string? name = null) where T : struct, IExcelRow<T>
|
||||
=> this.Excel.GetSheet<T>(language?.ToLumina(), name);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ExcelSheet<T>? GetExcelSheet<T>(ClientLanguage language) where T : ExcelRow
|
||||
=> this.Excel.GetSheet<T>(language.ToLumina());
|
||||
public SubrowExcelSheet<T> GetSubrowExcelSheet<T>(ClientLanguage? language = null, string? name = null) where T : struct, IExcelSubrow<T>
|
||||
=> this.Excel.GetSubrowSheet<T>(language?.ToLumina(), name);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FileResource? GetFile(string path)
|
||||
|
|
@ -170,6 +171,7 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
|
|||
{
|
||||
this.luminaCancellationTokenSource.Cancel();
|
||||
this.GameData.Dispose();
|
||||
this.rsvResolver.Dispose();
|
||||
}
|
||||
|
||||
private class LauncherTroubleshootingInfo
|
||||
|
|
|
|||
22
Dalamud/Data/LuminaUtils.cs
Normal file
22
Dalamud/Data/LuminaUtils.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using Lumina.Excel;
|
||||
|
||||
namespace Dalamud.Data;
|
||||
|
||||
/// <summary>
|
||||
/// A helper class to easily resolve Lumina data within Dalamud.
|
||||
/// </summary>
|
||||
internal static class LuminaUtils
|
||||
{
|
||||
private static ExcelModule Module => Service<DataManager>.Get().Excel;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RowRef{T}"/> class using the default <see cref="ExcelModule"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of Lumina sheet to resolve.</typeparam>
|
||||
/// <param name="rowId">The id of the row to resolve.</param>
|
||||
/// <returns>A new <see cref="RowRef{T}"/> object.</returns>
|
||||
public static RowRef<T> CreateRef<T>(uint rowId) where T : struct, IExcelRow<T>
|
||||
{
|
||||
return new(Module, rowId);
|
||||
}
|
||||
}
|
||||
51
Dalamud/Data/RsvResolver.cs
Normal file
51
Dalamud/Data/RsvResolver.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue