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:
Asriel Camora 2024-10-20 19:59:03 -07:00 committed by GitHub
parent 08d8605871
commit 0b9af0e3f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 460 additions and 403 deletions

View file

@ -1,6 +1,9 @@
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Data;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using Lumina.Excel;
namespace Dalamud.Game.ClientState.Aetherytes;
/// <summary>
@ -56,7 +59,7 @@ public interface IAetheryteEntry
/// <summary>
/// Gets the Aetheryte data related to this aetheryte.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.Aetheryte> AetheryteData { get; }
RowRef<Lumina.Excel.Sheets.Aetheryte> AetheryteData { get; }
}
/// <summary>
@ -103,5 +106,5 @@ internal sealed class AetheryteEntry : IAetheryteEntry
public bool IsApartment => this.data.IsApartment;
/// <inheritdoc />
public ExcelResolver<Lumina.Excel.GeneratedSheets.Aetheryte> AetheryteData => new(this.AetheryteId);
public RowRef<Lumina.Excel.Sheets.Aetheryte> AetheryteData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Aetheryte>(this.AetheryteId);
}

View file

@ -1,6 +1,8 @@
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.ClientState.Resolvers;
using Lumina.Excel;
namespace Dalamud.Game.ClientState.Buddy;
@ -45,17 +47,17 @@ public interface IBuddyMember
/// <summary>
/// Gets the Mount data related to this buddy. It should only be used with companion buddies.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.Mount> MountData { get; }
RowRef<Lumina.Excel.Sheets.Mount> MountData { get; }
/// <summary>
/// Gets the Pet data related to this buddy. It should only be used with pet buddies.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.Pet> PetData { get; }
RowRef<Lumina.Excel.Sheets.Pet> PetData { get; }
/// <summary>
/// Gets the Trust data related to this buddy. It should only be used with battle buddies.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.DawnGrowMember> TrustData { get; }
RowRef<Lumina.Excel.Sheets.DawnGrowMember> TrustData { get; }
}
/// <summary>
@ -94,13 +96,13 @@ internal unsafe class BuddyMember : IBuddyMember
public uint DataID => this.Struct->DataId;
/// <inheritdoc />
public ExcelResolver<Lumina.Excel.GeneratedSheets.Mount> MountData => new(this.DataID);
public RowRef<Lumina.Excel.Sheets.Mount> MountData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Mount>(this.DataID);
/// <inheritdoc />
public ExcelResolver<Lumina.Excel.GeneratedSheets.Pet> PetData => new(this.DataID);
public RowRef<Lumina.Excel.Sheets.Pet> PetData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Pet>(this.DataID);
/// <inheritdoc />
public ExcelResolver<Lumina.Excel.GeneratedSheets.DawnGrowMember> TrustData => new(this.DataID);
public RowRef<Lumina.Excel.Sheets.DawnGrowMember> TrustData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.DawnGrowMember>(this.DataID);
private FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember* Struct => (FFXIVClientStructs.FFXIV.Client.Game.UI.Buddy.BuddyMember*)this.Address;
}

View file

@ -19,7 +19,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Event;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.Sheets;
using Action = System.Action;

View file

@ -1,10 +1,11 @@
using System.Numerics;
using Dalamud.Data;
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Memory;
using Lumina.Excel;
namespace Dalamud.Game.ClientState.Fates;
/// <summary>
@ -20,7 +21,7 @@ public interface IFate : IEquatable<IFate>
/// <summary>
/// Gets game data linked to this Fate.
/// </summary>
Lumina.Excel.GeneratedSheets.Fate GameData { get; }
RowRef<Lumina.Excel.Sheets.Fate> GameData { get; }
/// <summary>
/// Gets the time this <see cref="Fate"/> started.
@ -105,7 +106,7 @@ public interface IFate : IEquatable<IFate>
/// <summary>
/// Gets the territory this <see cref="Fate"/> is located in.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.TerritoryType> TerritoryType { get; }
RowRef<Lumina.Excel.Sheets.TerritoryType> TerritoryType { get; }
/// <summary>
/// Gets the address of this Fate in memory.
@ -185,7 +186,7 @@ internal unsafe partial class Fate : IFate
public ushort FateId => this.Struct->FateId;
/// <inheritdoc/>
public Lumina.Excel.GeneratedSheets.Fate GameData => Service<DataManager>.Get().GetExcelSheet<Lumina.Excel.GeneratedSheets.Fate>().GetRow(this.FateId);
public RowRef<Lumina.Excel.Sheets.Fate> GameData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Fate>(this.FateId);
/// <inheritdoc/>
public int StartTimeEpoch => this.Struct->StartTimeEpoch;
@ -238,5 +239,5 @@ internal unsafe partial class Fate : IFate
/// <summary>
/// Gets the territory this <see cref="Fate"/> is located in.
/// </summary>
public ExcelResolver<Lumina.Excel.GeneratedSheets.TerritoryType> TerritoryType => new(this.Struct->TerritoryId);
public RowRef<Lumina.Excel.Sheets.TerritoryType> TerritoryType => LuminaUtils.CreateRef<Lumina.Excel.Sheets.TerritoryType>(this.Struct->TerritoryId);
}

View file

@ -29,13 +29,13 @@ public unsafe class SMNGauge : JobGaugeBase<SummonerGauge>
/// <summary>
/// Gets the summon that will return after the current summon expires.
/// This maps to the <see cref="Lumina.Excel.GeneratedSheets.Pet"/> sheet.
/// This maps to the <see cref="Lumina.Excel.Sheets.Pet"/> sheet.
/// </summary>
public SummonPet ReturnSummon => (SummonPet)this.Struct->ReturnSummon;
/// <summary>
/// Gets the summon glam for the <see cref="ReturnSummon"/>.
/// This maps to the <see cref="Lumina.Excel.GeneratedSheets.PetMirage"/> sheet.
/// This maps to the <see cref="Lumina.Excel.Sheets.PetMirage"/> sheet.
/// </summary>
public PetGlam ReturnSummonGlam => (PetGlam)this.Struct->ReturnSummonGlam;

View file

@ -1,12 +1,8 @@
using System.Numerics;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Game.ClientState.Statuses;
using Dalamud.Game.Text.SeStringHandling;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.ClientState.Objects.SubKinds;
@ -16,14 +12,14 @@ namespace Dalamud.Game.ClientState.Objects.SubKinds;
public interface IPlayerCharacter : IBattleChara
{
/// <summary>
/// Gets the current <see cref="ExcelResolver{T}">world</see> of the character.
/// Gets the current <see cref="RowRef{T}">world</see> of the character.
/// </summary>
ExcelResolver<World> CurrentWorld { get; }
RowRef<World> CurrentWorld { get; }
/// <summary>
/// Gets the home <see cref="ExcelResolver{T}">world</see> of the character.
/// Gets the home <see cref="RowRef{T}">world</see> of the character.
/// </summary>
ExcelResolver<World> HomeWorld { get; }
RowRef<World> HomeWorld { get; }
}
/// <summary>
@ -42,10 +38,10 @@ internal unsafe class PlayerCharacter : BattleChara, IPlayerCharacter
}
/// <inheritdoc/>
public ExcelResolver<World> CurrentWorld => new(this.Struct->CurrentWorld);
public RowRef<World> CurrentWorld => LuminaUtils.CreateRef<World>(this.Struct->CurrentWorld);
/// <inheritdoc/>
public ExcelResolver<World> HomeWorld => new(this.Struct->HomeWorld);
public RowRef<World> HomeWorld => LuminaUtils.CreateRef<World>(this.Struct->HomeWorld);
/// <summary>
/// Gets the target actor ID of the PlayerCharacter.

View file

@ -1,10 +1,12 @@
using System.Runtime.CompilerServices;
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Memory;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.ClientState.Objects.Types;
@ -61,7 +63,7 @@ public interface ICharacter : IGameObject
/// <summary>
/// Gets the ClassJob of this Chara.
/// </summary>
public ExcelResolver<ClassJob> ClassJob { get; }
public RowRef<ClassJob> ClassJob { get; }
/// <summary>
/// Gets the level of this Chara.
@ -87,7 +89,7 @@ public interface ICharacter : IGameObject
/// <summary>
/// Gets the current online status of the character.
/// </summary>
public ExcelResolver<OnlineStatus> OnlineStatus { get; }
public RowRef<OnlineStatus> OnlineStatus { get; }
/// <summary>
/// Gets the status flags.
@ -97,14 +99,14 @@ public interface ICharacter : IGameObject
/// <summary>
/// Gets the current mount for this character. Will be <c>null</c> if the character doesn't have a mount.
/// </summary>
public ExcelResolver<Mount>? CurrentMount { get; }
public RowRef<Mount>? CurrentMount { get; }
/// <summary>
/// Gets the current minion summoned for this character. Will be <c>null</c> if the character doesn't have a minion.
/// This method *will* return information about a spawned (but invisible) minion, e.g. if the character is riding a
/// mount.
/// </summary>
public ExcelResolver<Companion>? CurrentMinion { get; }
public RowRef<Companion>? CurrentMinion { get; }
}
/// <summary>
@ -150,7 +152,7 @@ internal unsafe class Character : GameObject, ICharacter
public byte ShieldPercentage => this.Struct->CharacterData.ShieldValue;
/// <inheritdoc/>
public ExcelResolver<ClassJob> ClassJob => new(this.Struct->CharacterData.ClassJob);
public RowRef<ClassJob> ClassJob => LuminaUtils.CreateRef<ClassJob>(this.Struct->CharacterData.ClassJob);
/// <inheritdoc/>
public byte Level => this.Struct->CharacterData.Level;
@ -170,7 +172,7 @@ internal unsafe class Character : GameObject, ICharacter
public uint NameId => this.Struct->NameId;
/// <inheritdoc/>
public ExcelResolver<OnlineStatus> OnlineStatus => new(this.Struct->CharacterData.OnlineStatus);
public RowRef<OnlineStatus> OnlineStatus => LuminaUtils.CreateRef<OnlineStatus>(this.Struct->CharacterData.OnlineStatus);
/// <summary>
/// Gets the status flags.
@ -186,28 +188,28 @@ internal unsafe class Character : GameObject, ICharacter
(this.Struct->IsCasting ? StatusFlags.IsCasting : StatusFlags.None);
/// <inheritdoc />
public ExcelResolver<Mount>? CurrentMount
public RowRef<Mount>? CurrentMount
{
get
{
if (this.Struct->IsNotMounted()) return null; // just for safety.
var mountId = this.Struct->Mount.MountId;
return mountId == 0 ? null : new ExcelResolver<Mount>(mountId);
return mountId == 0 ? null : LuminaUtils.CreateRef<Mount>(mountId);
}
}
/// <inheritdoc />
public ExcelResolver<Companion>? CurrentMinion
public RowRef<Companion>? CurrentMinion
{
get
{
if (this.Struct->CompanionObject != null)
return new ExcelResolver<Companion>(this.Struct->CompanionObject->BaseId);
return LuminaUtils.CreateRef<Companion>(this.Struct->CompanionObject->BaseId);
// this is only present if a minion is summoned but hidden (e.g. the player's on a mount).
var hiddenCompanionId = this.Struct->CompanionData.CompanionId;
return hiddenCompanionId == 0 ? null : new ExcelResolver<Companion>(hiddenCompanionId);
return hiddenCompanionId == 0 ? null : LuminaUtils.CreateRef<Companion>(hiddenCompanionId);
}
}

View file

@ -1,13 +1,15 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Game.ClientState.Statuses;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Memory;
using Lumina.Excel;
namespace Dalamud.Game.ClientState.Party;
/// <summary>
@ -71,12 +73,12 @@ public interface IPartyMember
/// <summary>
/// Gets the territory this party member is located in.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.TerritoryType> Territory { get; }
RowRef<Lumina.Excel.Sheets.TerritoryType> Territory { get; }
/// <summary>
/// Gets the World this party member resides in.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.World> World { get; }
RowRef<Lumina.Excel.Sheets.World> World { get; }
/// <summary>
/// Gets the displayname of this party member.
@ -91,7 +93,7 @@ public interface IPartyMember
/// <summary>
/// Gets the classjob of this party member.
/// </summary>
ExcelResolver<Lumina.Excel.GeneratedSheets.ClassJob> ClassJob { get; }
RowRef<Lumina.Excel.Sheets.ClassJob> ClassJob { get; }
/// <summary>
/// Gets the level of this party member.
@ -169,12 +171,12 @@ internal unsafe class PartyMember : IPartyMember
/// <summary>
/// Gets the territory this party member is located in.
/// </summary>
public ExcelResolver<Lumina.Excel.GeneratedSheets.TerritoryType> Territory => new(this.Struct->TerritoryType);
public RowRef<Lumina.Excel.Sheets.TerritoryType> Territory => LuminaUtils.CreateRef<Lumina.Excel.Sheets.TerritoryType>(this.Struct->TerritoryType);
/// <summary>
/// Gets the World this party member resides in.
/// </summary>
public ExcelResolver<Lumina.Excel.GeneratedSheets.World> World => new(this.Struct->HomeWorld);
public RowRef<Lumina.Excel.Sheets.World> World => LuminaUtils.CreateRef<Lumina.Excel.Sheets.World>(this.Struct->HomeWorld);
/// <summary>
/// Gets the displayname of this party member.
@ -189,7 +191,7 @@ internal unsafe class PartyMember : IPartyMember
/// <summary>
/// Gets the classjob of this party member.
/// </summary>
public ExcelResolver<Lumina.Excel.GeneratedSheets.ClassJob> ClassJob => new(this.Struct->ClassJob);
public RowRef<Lumina.Excel.Sheets.ClassJob> ClassJob => LuminaUtils.CreateRef<Lumina.Excel.Sheets.ClassJob>(this.Struct->ClassJob);
/// <summary>
/// Gets the level of this party member.

View file

@ -1,38 +0,0 @@
using Dalamud.Data;
using Lumina.Excel;
namespace Dalamud.Game.ClientState.Resolvers;
/// <summary>
/// This object resolves a rowID within an Excel sheet.
/// </summary>
/// <typeparam name="T">The type of Lumina sheet to resolve.</typeparam>
public class ExcelResolver<T> where T : ExcelRow
{
/// <summary>
/// Initializes a new instance of the <see cref="ExcelResolver{T}"/> class.
/// </summary>
/// <param name="id">The ID of the classJob.</param>
internal ExcelResolver(uint id)
{
this.Id = id;
}
/// <summary>
/// Gets the ID to be resolved.
/// </summary>
public uint Id { get; }
/// <summary>
/// Gets GameData linked to this excel row.
/// </summary>
public T? GameData => Service<DataManager>.Get().GetExcelSheet<T>()?.GetRow(this.Id);
/// <summary>
/// Gets GameData linked to this excel row with the specified language.
/// </summary>
/// <param name="language">The language.</param>
/// <returns>The ExcelRow in the specified language.</returns>
public T? GetWithLanguage(ClientLanguage language) => Service<DataManager>.Get().GetExcelSheet<T>(language)?.GetRow(this.Id);
}

View file

@ -1,6 +1,8 @@
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.ClientState.Resolvers;
using Lumina.Excel;
namespace Dalamud.Game.ClientState.Statuses;
@ -31,7 +33,7 @@ public unsafe class Status
/// <summary>
/// Gets the GameData associated with this status.
/// </summary>
public Lumina.Excel.GeneratedSheets.Status GameData => new ExcelResolver<Lumina.Excel.GeneratedSheets.Status>(this.Struct->StatusId).GameData;
public RowRef<Lumina.Excel.Sheets.Status> GameData => LuminaUtils.CreateRef<Lumina.Excel.Sheets.Status>(this.Struct->StatusId);
/// <summary>
/// Gets the parameter value of the status.

View file

@ -1,7 +1,7 @@
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.Gui.ContextMenu;

View file

@ -1,11 +1,12 @@
using Dalamud.Data;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Game.Network.Structures.InfoProxy;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.Gui.ContextMenu;
@ -46,7 +47,7 @@ public sealed unsafe class MenuTargetDefault : MenuTarget
/// <summary>
/// Gets the home world id of the target.
/// </summary>
public ExcelResolver<World> TargetHomeWorld => new((uint)this.Context->TargetHomeWorldId);
public RowRef<World> TargetHomeWorld => LuminaUtils.CreateRef<World>((uint)this.Context->TargetHomeWorldId);
/// <summary>
/// Gets the currently targeted character. Only shows up for specific targets, like friends, party finder listings, or party members.

View file

@ -1,5 +1,5 @@
using Dalamud.Plugin.Services;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.Gui.PartyFinder.Types;

View file

@ -5,7 +5,8 @@ using Dalamud.Data;
using Dalamud.Game.Gui.PartyFinder.Internal;
using Dalamud.Game.Text.SeStringHandling;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.Gui.PartyFinder.Types;
@ -48,7 +49,7 @@ public interface IPartyFinderListing
/// <summary>
/// Gets a list of the classes/jobs that are currently present in the party.
/// </summary>
IReadOnlyCollection<Lazy<ClassJob>> JobsPresent { get; }
IReadOnlyCollection<RowRef<ClassJob>> JobsPresent { get; }
/// <summary>
/// Gets the ID assigned to this listing by the game's server.
@ -73,17 +74,17 @@ public interface IPartyFinderListing
/// <summary>
/// Gets the world that this listing was created on.
/// </summary>
Lazy<World> World { get; }
RowRef<World> World { get; }
/// <summary>
/// Gets the home world of the listing's host.
/// </summary>
Lazy<World> HomeWorld { get; }
RowRef<World> HomeWorld { get; }
/// <summary>
/// Gets the current world of the listing's host.
/// </summary>
Lazy<World> CurrentWorld { get; }
RowRef<World> CurrentWorld { get; }
/// <summary>
/// Gets the Party Finder category this listing is listed under.
@ -98,7 +99,7 @@ public interface IPartyFinderListing
/// <summary>
/// Gets the duty this listing is for. May be null for non-duty listings.
/// </summary>
Lazy<ContentFinderCondition> Duty { get; }
RowRef<ContentFinderCondition> Duty { get; }
/// <summary>
/// Gets the type of duty this listing is for.
@ -216,12 +217,12 @@ internal class PartyFinderListing : IPartyFinderListing
this.ContentId = listing.ContentId;
this.Name = SeString.Parse(listing.Name.TakeWhile(b => b != 0).ToArray());
this.Description = SeString.Parse(listing.Description.TakeWhile(b => b != 0).ToArray());
this.World = new Lazy<World>(() => dataManager.GetExcelSheet<World>().GetRow(listing.World));
this.HomeWorld = new Lazy<World>(() => dataManager.GetExcelSheet<World>().GetRow(listing.HomeWorld));
this.CurrentWorld = new Lazy<World>(() => dataManager.GetExcelSheet<World>().GetRow(listing.CurrentWorld));
this.World = LuminaUtils.CreateRef<World>(listing.World);
this.HomeWorld = LuminaUtils.CreateRef<World>(listing.HomeWorld);
this.CurrentWorld = LuminaUtils.CreateRef<World>(listing.CurrentWorld);
this.Category = (DutyCategory)listing.Category;
this.RawDuty = listing.Duty;
this.Duty = new Lazy<ContentFinderCondition>(() => dataManager.GetExcelSheet<ContentFinderCondition>().GetRow(listing.Duty));
this.Duty = LuminaUtils.CreateRef<ContentFinderCondition>(listing.Duty);
this.DutyType = (DutyType)listing.DutyType;
this.BeginnersWelcome = listing.BeginnersWelcome == 1;
this.SecondsRemaining = listing.SecondsRemaining;
@ -231,10 +232,7 @@ internal class PartyFinderListing : IPartyFinderListing
this.SlotsFilled = listing.NumSlotsFilled;
this.LastPatchHotfixTimestamp = listing.LastPatchHotfixTimestamp;
this.JobsPresent = listing.JobsPresent
.Select(id => new Lazy<ClassJob>(
() => id == 0
? null
: dataManager.GetExcelSheet<ClassJob>().GetRow(id)))
.Select(id => LuminaUtils.CreateRef<ClassJob>(id))
.ToArray();
}
@ -251,13 +249,13 @@ internal class PartyFinderListing : IPartyFinderListing
public SeString Description { get; }
/// <inheritdoc/>
public Lazy<World> World { get; }
public RowRef<World> World { get; }
/// <inheritdoc/>
public Lazy<World> HomeWorld { get; }
public RowRef<World> HomeWorld { get; }
/// <inheritdoc/>
public Lazy<World> CurrentWorld { get; }
public RowRef<World> CurrentWorld { get; }
/// <inheritdoc/>
public DutyCategory Category { get; }
@ -266,7 +264,7 @@ internal class PartyFinderListing : IPartyFinderListing
public ushort RawDuty { get; }
/// <inheritdoc/>
public Lazy<ContentFinderCondition> Duty { get; }
public RowRef<ContentFinderCondition> Duty { get; }
/// <inheritdoc/>
public DutyType DutyType { get; }
@ -314,7 +312,7 @@ internal class PartyFinderListing : IPartyFinderListing
public IReadOnlyCollection<byte> RawJobsPresent => this.jobsPresent;
/// <inheritdoc/>
public IReadOnlyCollection<Lazy<ClassJob>> JobsPresent { get; }
public IReadOnlyCollection<RowRef<ClassJob>> JobsPresent { get; }
#region Indexers

View file

@ -46,7 +46,7 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader
var uploadObject = new UniversalisItemUploadRequest
{
WorldId = clientState.LocalPlayer?.CurrentWorld.Id ?? 0,
WorldId = clientState.LocalPlayer?.CurrentWorld.RowId ?? 0,
UploaderId = uploader.ToString(),
ItemId = request.Listings.FirstOrDefault()?.CatalogId ?? 0,
Listings = [],
@ -120,7 +120,7 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader
var taxUploadObject = new UniversalisTaxUploadRequest
{
WorldId = clientState.LocalPlayer?.CurrentWorld.Id ?? 0,
WorldId = clientState.LocalPlayer?.CurrentWorld.RowId ?? 0,
UploaderId = clientState.LocalContentId.ToString(),
TaxData = new UniversalisTaxData
{
@ -158,7 +158,7 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader
return;
var itemId = purchaseHandler.CatalogId;
var worldId = clientState.LocalPlayer?.CurrentWorld.Id ?? 0;
var worldId = clientState.LocalPlayer?.CurrentWorld.RowId ?? 0;
// ====================================================================================

View file

@ -16,7 +16,7 @@ using Dalamud.Hooking;
using Dalamud.Networking.Http;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.UI.Info;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.Sheets;
using Serilog;
namespace Dalamud.Game.Network.Internal;
@ -282,21 +282,17 @@ internal unsafe class NetworkHandlers : IInternalDisposableService
if (this.configuration.DutyFinderTaskbarFlash)
Util.FlashWindow();
var cfConditionSheet = Service<DataManager>.Get().GetExcelSheet<ContentFinderCondition>()!;
var cfCondition = cfConditionSheet.GetRow(conditionId);
var cfCondition = LuminaUtils.CreateRef<ContentFinderCondition>(conditionId);
if (cfCondition == null)
if (!cfCondition.IsValid)
{
Log.Error("CFC key {ConditionId} not in Lumina data", conditionId);
return result;
}
var cfcName = cfCondition.Name.ToDalamudString();
var cfcName = cfCondition.Value.Name.ToDalamudString();
if (cfcName.Payloads.Count == 0)
{
cfcName = "Duty Roulette";
cfCondition.Image = 112324;
}
Task.Run(() =>
{
@ -308,7 +304,7 @@ internal unsafe class NetworkHandlers : IInternalDisposableService
Service<ChatGui>.GetNullable()?.Print(b.Build());
}
this.CfPop.InvokeSafely(cfCondition);
this.CfPop.InvokeSafely(cfCondition.Value);
}).ContinueWith(
task => Log.Error(task.Exception, "CfPop.Invoke failed"),
TaskContinuationOptions.OnlyOnFaulted);

View file

@ -1,11 +1,11 @@
using System.Collections.Generic;
using Dalamud.Game.ClientState.Resolvers;
using Dalamud.Memory;
using Dalamud.Data;
using FFXIVClientStructs.FFXIV.Client.UI.Info;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel;
using Lumina.Excel.Sheets;
namespace Dalamud.Game.Network.Structures.InfoProxy;
@ -92,15 +92,15 @@ public unsafe class CharacterData
/// <summary>
/// Gets the applicable statues of the character.
/// </summary>
public IReadOnlyList<ExcelResolver<OnlineStatus>> Statuses
public IReadOnlyList<RowRef<OnlineStatus>> Statuses
{
get
{
var statuses = new List<ExcelResolver<OnlineStatus>>();
var statuses = new List<RowRef<OnlineStatus>>();
for (var i = 0; i < 64; i++)
{
if ((this.StatusMask & (1UL << i)) != 0)
statuses.Add(new((uint)i));
statuses.Add(LuminaUtils.CreateRef<OnlineStatus>((uint)i));
}
return statuses;
@ -125,22 +125,22 @@ public unsafe class CharacterData
/// <summary>
/// Gets the current world of the character.
/// </summary>
public ExcelResolver<World> CurrentWorld => new(this.Struct->CurrentWorld);
public RowRef<World> CurrentWorld => LuminaUtils.CreateRef<World>(this.Struct->CurrentWorld);
/// <summary>
/// Gets the home world of the character.
/// </summary>
public ExcelResolver<World> HomeWorld => new(this.Struct->HomeWorld);
public RowRef<World> HomeWorld => LuminaUtils.CreateRef<World>(this.Struct->HomeWorld);
/// <summary>
/// Gets the location of the character.
/// </summary>
public ExcelResolver<TerritoryType> Location => new(this.Struct->Location);
public RowRef<TerritoryType> Location => LuminaUtils.CreateRef<TerritoryType>(this.Struct->Location);
/// <summary>
/// Gets the grand company of the character.
/// </summary>
public ExcelResolver<GrandCompany> GrandCompany => new((uint)this.Struct->GrandCompany);
public RowRef<GrandCompany> GrandCompany => LuminaUtils.CreateRef<GrandCompany>((uint)this.Struct->GrandCompany);
/// <summary>
/// Gets the primary client language of the character.
@ -178,7 +178,7 @@ public unsafe class CharacterData
/// <summary>
/// Gets the job of the character.
/// </summary>
public ExcelResolver<ClassJob> ClassJob => new(this.Struct->Job);
public RowRef<ClassJob> ClassJob => LuminaUtils.CreateRef<ClassJob>(this.Struct->Job);
/// <summary>
/// Gets the name of the character.

View file

@ -38,13 +38,6 @@ public abstract partial class Payload
/// </summary>
public bool Dirty { get; protected set; } = true;
/// <summary>
/// Gets the Lumina instance to use for any necessary data lookups.
/// </summary>
[JsonIgnore]
// TODO: We should refactor this. It should not be possible to get IDataManager through here.
protected IDataManager DataResolver => Service<DataManager>.Get();
/// <summary>
/// Decodes a binary representation of a payload into its corresponding nice object payload.
/// </summary>

View file

@ -2,7 +2,11 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel.Sheets;
using Lumina.Text.ReadOnly;
using Newtonsoft.Json;
using Serilog;
@ -106,28 +110,28 @@ public class AutoTranslatePayload : Payload, ITextProvider
this.Key = GetInteger(reader);
}
private static ReadOnlySeString ResolveTextCommand(TextCommand command)
{
// TextCommands prioritize the `Alias` field, if it not empty
// Example for this is /rangerpose2l which becomes /blackrangerposeb in chat
return !command.Alias.IsEmpty ? command.Alias : command.Command;
}
private string Resolve()
{
string value = null;
var sheet = this.DataResolver.GetExcelSheet<Completion>();
var excelModule = Service<DataManager>.Get().Excel;
var completionSheet = excelModule.GetSheet<Completion>();
Completion row = null;
try
{
// try to get the row in the Completion table itself, because this is 'easiest'
// The row may not exist at all (if the Key is for another table), or it could be the wrong row
// (again, if it's meant for another table)
row = sheet.GetRow(this.Key);
}
catch
{
} // don't care, row will be null
// try to get the row in the Completion table itself, because this is 'easiest'
// The row may not exist at all (if the Key is for another table), or it could be the wrong row
// (again, if it's meant for another table)
if (row?.Group == this.Group)
if (completionSheet.GetRowOrDefault(this.Key) is { } completion && completion.Group == this.Group)
{
// if the row exists in this table and the group matches, this is actually the correct data
value = row.Text;
value = completion.Text.ExtractText();
}
else
{
@ -135,34 +139,34 @@ public class AutoTranslatePayload : Payload, ITextProvider
{
// we need to get the linked table and do the lookup there instead
// in this case, there will only be one entry for this group id
row = sheet.First(r => r.Group == this.Group);
var row = completionSheet.First(r => r.Group == this.Group);
// many of the names contain valid id ranges after the table name, but we don't need those
var actualTableName = row.LookupTable.RawString.Split('[')[0];
var actualTableName = row.LookupTable.ExtractText().Split('[')[0];
var name = actualTableName switch
{
"Action" => this.DataResolver.GetExcelSheet<Lumina.Excel.GeneratedSheets.Action>().GetRow(this.Key).Name,
"ActionComboRoute" => this.DataResolver.GetExcelSheet<ActionComboRoute>().GetRow(this.Key).Name,
"BuddyAction" => this.DataResolver.GetExcelSheet<BuddyAction>().GetRow(this.Key).Name,
"ClassJob" => this.DataResolver.GetExcelSheet<ClassJob>().GetRow(this.Key).Name,
"Companion" => this.DataResolver.GetExcelSheet<Companion>().GetRow(this.Key).Singular,
"CraftAction" => this.DataResolver.GetExcelSheet<CraftAction>().GetRow(this.Key).Name,
"GeneralAction" => this.DataResolver.GetExcelSheet<GeneralAction>().GetRow(this.Key).Name,
"GuardianDeity" => this.DataResolver.GetExcelSheet<GuardianDeity>().GetRow(this.Key).Name,
"MainCommand" => this.DataResolver.GetExcelSheet<MainCommand>().GetRow(this.Key).Name,
"Mount" => this.DataResolver.GetExcelSheet<Mount>().GetRow(this.Key).Singular,
"Pet" => this.DataResolver.GetExcelSheet<Pet>().GetRow(this.Key).Name,
"PetAction" => this.DataResolver.GetExcelSheet<PetAction>().GetRow(this.Key).Name,
"PetMirage" => this.DataResolver.GetExcelSheet<PetMirage>().GetRow(this.Key).Name,
"PlaceName" => this.DataResolver.GetExcelSheet<PlaceName>().GetRow(this.Key).Name,
"Race" => this.DataResolver.GetExcelSheet<Race>().GetRow(this.Key).Masculine,
"TextCommand" => this.ResolveTextCommand(),
"Tribe" => this.DataResolver.GetExcelSheet<Tribe>().GetRow(this.Key).Masculine,
"Weather" => this.DataResolver.GetExcelSheet<Weather>().GetRow(this.Key).Name,
"Action" => excelModule.GetSheet<Lumina.Excel.Sheets.Action>().GetRow(this.Key).Name,
"ActionComboRoute" => excelModule.GetSheet<ActionComboRoute>().GetRow(this.Key).Name,
"BuddyAction" => excelModule.GetSheet<BuddyAction>().GetRow(this.Key).Name,
"ClassJob" => excelModule.GetSheet<ClassJob>().GetRow(this.Key).Name,
"Companion" => excelModule.GetSheet<Companion>().GetRow(this.Key).Singular,
"CraftAction" => excelModule.GetSheet<CraftAction>().GetRow(this.Key).Name,
"GeneralAction" => excelModule.GetSheet<GeneralAction>().GetRow(this.Key).Name,
"GuardianDeity" => excelModule.GetSheet<GuardianDeity>().GetRow(this.Key).Name,
"MainCommand" => excelModule.GetSheet<MainCommand>().GetRow(this.Key).Name,
"Mount" => excelModule.GetSheet<Mount>().GetRow(this.Key).Singular,
"Pet" => excelModule.GetSheet<Pet>().GetRow(this.Key).Name,
"PetAction" => excelModule.GetSheet<PetAction>().GetRow(this.Key).Name,
"PetMirage" => excelModule.GetSheet<PetMirage>().GetRow(this.Key).Name,
"PlaceName" => excelModule.GetSheet<PlaceName>().GetRow(this.Key).Name,
"Race" => excelModule.GetSheet<Race>().GetRow(this.Key).Masculine,
"TextCommand" => AutoTranslatePayload.ResolveTextCommand(excelModule.GetSheet<TextCommand>().GetRow(this.Key)),
"Tribe" => excelModule.GetSheet<Tribe>().GetRow(this.Key).Masculine,
"Weather" => excelModule.GetSheet<Weather>().GetRow(this.Key).Name,
_ => throw new Exception(actualTableName),
};
value = name;
value = name.ExtractText();
}
catch (Exception e)
{
@ -172,12 +176,4 @@ public class AutoTranslatePayload : Payload, ITextProvider
return value;
}
private Lumina.Text.SeString ResolveTextCommand()
{
// TextCommands prioritize the `Alias` field, if it not empty
// Example for this is /rangerpose2l which becomes /blackrangerposeb in chat
var result = this.DataResolver.GetExcelSheet<TextCommand>().GetRow(this.Key);
return result.Alias.Payloads.Count > 0 ? result.Alias : result.Command;
}
}

View file

@ -3,9 +3,10 @@ using System.IO;
using System.Linq;
using System.Text;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
using Serilog;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -14,8 +15,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class ItemPayload : Payload
{
private Item? item;
// mainly to allow overriding the name (for things like owo)
// TODO: even though this is present in some item links, it may not really have a use at all
// For things like owo, changing the text payload is probably correct, whereas changing the
@ -131,27 +130,13 @@ public class ItemPayload : Payload
public uint RawItemId => this.rawItemId;
/// <summary>
/// Gets the underlying Lumina Item represented by this payload.
/// Gets the underlying Lumina data represented by this payload. This is either a Item or EventItem <see cref="RowRef{T}"/>.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public Item? Item
{
get
{
// TODO(goat): This should be revamped/removed on an API level change.
if (this.Kind == ItemKind.EventItem)
{
Log.Warning("Event items cannot be fetched from the ItemPayload");
return null;
}
this.item ??= this.DataResolver.GetExcelSheet<Item>()!.GetRow(this.ItemId);
return this.item;
}
}
public RowRef Item =>
this.Kind == ItemKind.EventItem
? (RowRef)LuminaUtils.CreateRef<EventItem>(this.ItemId)
: (RowRef)LuminaUtils.CreateRef<Item>(this.ItemId);
/// <summary>
/// Gets a value indicating whether or not this item link is for a high-quality version of the item.
@ -183,7 +168,8 @@ public class ItemPayload : Payload
/// <inheritdoc/>
public override string ToString()
{
return $"{this.Type} - ItemId: {this.ItemId}, Kind: {this.Kind}, Name: {this.displayName ?? this.Item?.Name}";
var name = this.displayName ?? (this.Item.GetValueOrDefault<Item>()?.Name ?? this.Item.GetValueOrDefault<EventItem>()?.Name)?.ExtractText();
return $"{this.Type} - ItemId: {this.ItemId}, Kind: {this.Kind}, Name: {name}";
}
/// <inheritdoc/>

View file

@ -1,7 +1,10 @@
using System.Collections.Generic;
using System.IO;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -11,11 +14,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class MapLinkPayload : Payload
{
private Map map;
private TerritoryType territoryType;
private string placeNameRegion;
private string placeName;
[JsonProperty]
private uint territoryTypeId;
@ -38,8 +36,8 @@ public class MapLinkPayload : Payload
// this fudge is necessary basically to ensure we don't shift down a full tenth
// because essentially values are truncated instead of rounded, so 3.09999f will become
// 3.0f and not 3.1f
this.RawX = this.ConvertMapCoordinateToRawPosition(niceXCoord + fudgeFactor, this.Map.SizeFactor, this.Map.OffsetX);
this.RawY = this.ConvertMapCoordinateToRawPosition(niceYCoord + fudgeFactor, this.Map.SizeFactor, this.Map.OffsetY);
this.RawX = this.ConvertMapCoordinateToRawPosition(niceXCoord + fudgeFactor, this.Map.Value.SizeFactor, this.Map.Value.OffsetX);
this.RawY = this.ConvertMapCoordinateToRawPosition(niceYCoord + fudgeFactor, this.Map.Value.SizeFactor, this.Map.Value.OffsetY);
}
/// <summary>
@ -72,20 +70,14 @@ public class MapLinkPayload : Payload
/// <summary>
/// Gets the Map specified for this map link.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public Map Map => this.map ??= this.DataResolver.GetExcelSheet<Map>().GetRow(this.mapId);
public RowRef<Map> Map => LuminaUtils.CreateRef<Map>(this.mapId);
/// <summary>
/// Gets the TerritoryType specified for this map link.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public TerritoryType TerritoryType => this.territoryType ??= this.DataResolver.GetExcelSheet<TerritoryType>().GetRow(this.territoryTypeId);
public RowRef<TerritoryType> TerritoryType => LuminaUtils.CreateRef<TerritoryType>(this.territoryTypeId);
/// <summary>
/// Gets the internal x-coordinate for this map position.
@ -102,13 +94,13 @@ public class MapLinkPayload : Payload
/// <summary>
/// Gets the readable x-coordinate position for this map link. This value is approximate and unrounded.
/// </summary>
public float XCoord => this.ConvertRawPositionToMapCoordinate(this.RawX, this.Map.SizeFactor, this.Map.OffsetX);
public float XCoord => this.ConvertRawPositionToMapCoordinate(this.RawX, this.Map.Value.SizeFactor, this.Map.Value.OffsetX);
/// <summary>
/// Gets the readable y-coordinate position for this map link. This value is approximate and unrounded.
/// </summary>
[JsonIgnore]
public float YCoord => this.ConvertRawPositionToMapCoordinate(this.RawY, this.Map.SizeFactor, this.Map.OffsetY);
public float YCoord => this.ConvertRawPositionToMapCoordinate(this.RawY, this.Map.Value.SizeFactor, this.Map.Value.OffsetY);
// there is no Z; it's purely in the text payload where applicable
@ -143,18 +135,18 @@ public class MapLinkPayload : Payload
/// Gets the region name for this map link. This corresponds to the upper zone name found in the actual in-game map UI. eg, "La Noscea".
/// </summary>
[JsonIgnore]
public string PlaceNameRegion => this.placeNameRegion ??= this.TerritoryType.PlaceNameRegion.Value?.Name;
public string PlaceNameRegion => this.TerritoryType.Value.PlaceNameRegion.Value.Name.ExtractText();
/// <summary>
/// Gets the place name for this map link. This corresponds to the lower zone name found in the actual in-game map UI. eg, "Limsa Lominsa Upper Decks".
/// </summary>
[JsonIgnore]
public string PlaceName => this.placeName ??= this.TerritoryType.PlaceName.Value?.Name;
public string PlaceName => this.TerritoryType.Value.PlaceName.Value.Name.ExtractText();
/// <summary>
/// Gets the data string for this map link, for use by internal game functions that take a string variant and not a binary payload.
/// </summary>
public string DataString => $"m:{this.TerritoryType.RowId},{this.Map.RowId},{this.RawX},{this.RawY}";
public string DataString => $"m:{this.territoryTypeId},{this.mapId},{this.RawX},{this.RawY}";
/// <inheritdoc/>
public override string ToString()

View file

@ -2,7 +2,10 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -12,8 +15,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class PlayerPayload : Payload
{
private World world;
[JsonProperty]
private uint serverId;
@ -43,11 +44,8 @@ public class PlayerPayload : Payload
/// <summary>
/// Gets the Lumina object representing the player's home server.
/// </summary>
/// <remarks>
/// Value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public World World => this.world ??= this.DataResolver.GetExcelSheet<World>().GetRow(this.serverId);
public RowRef<World> World => LuminaUtils.CreateRef<World>(this.serverId);
/// <summary>
/// Gets or sets the player's displayed name. This does not contain the server name.
@ -72,7 +70,7 @@ public class PlayerPayload : Payload
/// The world name will always be present.
/// </summary>
[JsonIgnore]
public string DisplayedName => $"{this.PlayerName}{(char)SeIconChar.CrossWorld}{this.World.Name}";
public string DisplayedName => $"{this.PlayerName}{(char)SeIconChar.CrossWorld}{this.World.ValueNullable?.Name}";
/// <inheritdoc/>
public override PayloadType Type => PayloadType.Player;
@ -80,7 +78,7 @@ public class PlayerPayload : Payload
/// <inheritdoc/>
public override string ToString()
{
return $"{this.Type} - PlayerName: {this.PlayerName}, ServerId: {this.serverId}, ServerName: {this.World.Name}";
return $"{this.Type} - PlayerName: {this.PlayerName}, ServerId: {this.serverId}, ServerName: {this.World.ValueNullable?.Name}";
}
/// <inheritdoc/>

View file

@ -1,7 +1,10 @@
using System.Collections.Generic;
using System.IO;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -11,8 +14,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class QuestPayload : Payload
{
private Quest quest;
[JsonProperty]
private uint questId;
@ -40,16 +41,13 @@ public class QuestPayload : Payload
/// <summary>
/// Gets the underlying Lumina Quest represented by this payload.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public Quest Quest => this.quest ??= this.DataResolver.GetExcelSheet<Quest>().GetRow(this.questId);
public RowRef<Quest> Quest => LuminaUtils.CreateRef<Quest>(this.questId);
/// <inheritdoc />
public override string ToString()
{
return $"{this.Type} - QuestId: {this.questId}, Name: {this.Quest?.Name ?? "QUEST NOT FOUND"}";
return $"{this.Type} - QuestId: {this.questId}, Name: {this.Quest.ValueNullable?.Name.ExtractText() ?? "QUEST NOT FOUND"}";
}
/// <inheritdoc/>

View file

@ -1,7 +1,10 @@
using System.Collections.Generic;
using System.IO;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -11,8 +14,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class StatusPayload : Payload
{
private Status status;
[JsonProperty]
private uint statusId;
@ -40,16 +41,13 @@ public class StatusPayload : Payload
/// <summary>
/// Gets the Lumina Status object represented by this payload.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public Status Status => this.status ??= this.DataResolver.GetExcelSheet<Status>().GetRow(this.statusId);
public RowRef<Status> Status => LuminaUtils.CreateRef<Status>(this.statusId);
/// <inheritdoc/>
public override string ToString()
{
return $"{this.Type} - StatusId: {this.statusId}, Name: {this.Status.Name}";
return $"{this.Type} - StatusId: {this.statusId}, Name: {this.Status.ValueNullable?.Name}";
}
/// <inheritdoc/>

View file

@ -1,7 +1,10 @@
using System.Collections.Generic;
using System.IO;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -11,8 +14,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class UIForegroundPayload : Payload
{
private UIColor color;
[JsonProperty]
private ushort colorKey;
@ -51,11 +52,8 @@ public class UIForegroundPayload : Payload
/// <summary>
/// Gets a Lumina UIColor object representing this payload. The actual color data is at UIColor.UIForeground.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public UIColor UIColor => this.color ??= this.DataResolver.GetExcelSheet<UIColor>().GetRow(this.colorKey);
public RowRef<UIColor> UIColor => LuminaUtils.CreateRef<UIColor>(this.colorKey);
/// <summary>
/// Gets or sets the color key used as a lookup in the UIColor table for this foreground color.
@ -63,15 +61,11 @@ public class UIForegroundPayload : Payload
[JsonIgnore]
public ushort ColorKey
{
get
{
return this.colorKey;
}
get => this.colorKey;
set
{
this.colorKey = value;
this.color = null;
this.Dirty = true;
}
}
@ -80,13 +74,13 @@ public class UIForegroundPayload : Payload
/// Gets the Red/Green/Blue/Alpha values for this foreground color, encoded as a typical hex color.
/// </summary>
[JsonIgnore]
public uint RGBA => this.UIColor.UIForeground;
public uint RGBA => this.UIColor.Value.UIForeground;
/// <summary>
/// Gets the ABGR value for this foreground color, as ImGui requires it in PushColor.
/// </summary>
[JsonIgnore]
public uint ABGR => Interface.ColorHelpers.SwapEndianness(this.UIColor.UIForeground);
public uint ABGR => Interface.ColorHelpers.SwapEndianness(this.UIColor.Value.UIForeground);
/// <inheritdoc/>
public override string ToString()

View file

@ -1,7 +1,10 @@
using System.Collections.Generic;
using System.IO;
using Lumina.Excel.GeneratedSheets;
using Dalamud.Data;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling.Payloads;
@ -11,8 +14,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads;
/// </summary>
public class UIGlowPayload : Payload
{
private UIColor color;
[JsonProperty]
private ushort colorKey;
@ -57,7 +58,6 @@ public class UIGlowPayload : Payload
set
{
this.colorKey = value;
this.color = null;
this.Dirty = true;
}
}
@ -71,22 +71,19 @@ public class UIGlowPayload : Payload
/// Gets the Red/Green/Blue/Alpha values for this glow color, encoded as a typical hex color.
/// </summary>
[JsonIgnore]
public uint RGBA => this.UIColor.UIGlow;
public uint RGBA => this.UIColor.Value.UIGlow;
/// <summary>
/// Gets the ABGR value for this glow color, as ImGui requires it in PushColor.
/// </summary>
[JsonIgnore]
public uint ABGR => Interface.ColorHelpers.SwapEndianness(this.UIColor.UIGlow);
public uint ABGR => Interface.ColorHelpers.SwapEndianness(this.UIColor.Value.UIGlow);
/// <summary>
/// Gets a Lumina UIColor object representing this payload. The actual color data is at UIColor.UIGlow.
/// </summary>
/// <remarks>
/// The value is evaluated lazily and cached.
/// </remarks>
[JsonIgnore]
public UIColor UIColor => this.color ??= this.DataResolver.GetExcelSheet<UIColor>().GetRow(this.colorKey);
public RowRef<UIColor> UIColor => LuminaUtils.CreateRef<UIColor>(this.colorKey);
/// <inheritdoc/>
public override string ToString()

View file

@ -7,7 +7,7 @@ using System.Text;
using Dalamud.Data;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Utility;
using Lumina.Excel.GeneratedSheets;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Text.SeStringHandling;
@ -200,12 +200,12 @@ public class SeString
case ItemPayload.ItemKind.Normal:
case ItemPayload.ItemKind.Collectible:
case ItemPayload.ItemKind.Hq:
var item = data.GetExcelSheet<Item>()?.GetRow(itemId);
displayName = item?.Name;
var item = data.GetExcelSheet<Item>()?.GetRowOrDefault(itemId);
displayName = item?.Name.ExtractText();
rarity = item?.Rarity ?? 1;
break;
case ItemPayload.ItemKind.EventItem:
displayName = data.GetExcelSheet<EventItem>()?.GetRow(itemId)?.Name;
displayName = data.GetExcelSheet<EventItem>()?.GetRowOrDefault(itemId)?.Name.ExtractText();
break;
default:
throw new ArgumentOutOfRangeException(nameof(kind), kind, null);
@ -251,7 +251,7 @@ public class SeString
/// <returns>An SeString containing all the payloads necessary to display an item link in the chat log.</returns>
public static SeString CreateItemLink(Item item, bool isHq, string? displayNameOverride = null)
{
return CreateItemLink(item.RowId, isHq, displayNameOverride ?? item.Name);
return CreateItemLink(item.RowId, isHq, displayNameOverride ?? item.Name.ExtractText());
}
/// <summary>
@ -360,15 +360,14 @@ public class SeString
var mapSheet = data.GetExcelSheet<Map>();
var matches = data.GetExcelSheet<PlaceName>()
.Where(row => row.Name.ToString().ToLowerInvariant() == placeName.ToLowerInvariant())
.ToArray();
.Where(row => row.Name.ExtractText().Equals(placeName, StringComparison.InvariantCultureIgnoreCase));
foreach (var place in matches)
{
var map = mapSheet.FirstOrDefault(row => row.PlaceName.Row == place.RowId);
if (map != null && map.TerritoryType.Row != 0)
var map = mapSheet.Cast<Map?>().FirstOrDefault(row => row!.Value.PlaceName.RowId == place.RowId);
if (map.HasValue && map.Value.TerritoryType.RowId != 0)
{
return CreateMapLinkWithInstance(map.TerritoryType.Row, map.RowId, instance, xCoord, yCoord, fudgeFactor);
return CreateMapLinkWithInstance(map.Value.TerritoryType.RowId, map.Value.RowId, instance, xCoord, yCoord, fudgeFactor);
}
}