mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-02-23 08:17:47 +01:00
Optimizations
This commit is contained in:
parent
805615d9f4
commit
5204bb723d
8 changed files with 424 additions and 301 deletions
|
|
@ -1,4 +1,6 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
|
||||
|
|
@ -7,92 +9,160 @@ namespace Dalamud.Game.Inventory;
|
|||
/// <summary>
|
||||
/// Dalamud wrapper around a ClientStructs InventoryItem.
|
||||
/// </summary>
|
||||
public unsafe class GameInventoryItem
|
||||
[StructLayout(LayoutKind.Explicit, Size = StructSizeInBytes)]
|
||||
public unsafe struct GameInventoryItem : IEquatable<GameInventoryItem>
|
||||
{
|
||||
private InventoryItem internalItem;
|
||||
/// <summary>
|
||||
/// An empty instance of <see cref="GameInventoryItem"/>.
|
||||
/// </summary>
|
||||
internal static readonly GameInventoryItem Empty = default;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GameInventoryItem"/> class.
|
||||
/// The actual data.
|
||||
/// </summary>
|
||||
[FieldOffset(0)]
|
||||
internal readonly InventoryItem InternalItem;
|
||||
|
||||
private const int StructSizeInBytes = 0x38;
|
||||
|
||||
/// <summary>
|
||||
/// The view of the backing data, in <see cref="ulong"/>.
|
||||
/// </summary>
|
||||
[FieldOffset(0)]
|
||||
private fixed ulong dataUInt64[StructSizeInBytes / 0x8];
|
||||
|
||||
static GameInventoryItem()
|
||||
{
|
||||
Debug.Assert(
|
||||
sizeof(InventoryItem) == StructSizeInBytes,
|
||||
$"Definition of {nameof(InventoryItem)} has been changed. " +
|
||||
$"Update {nameof(StructSizeInBytes)} to {sizeof(InventoryItem)} to accommodate for the size change.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GameInventoryItem"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="item">Inventory item to wrap.</param>
|
||||
internal GameInventoryItem(InventoryItem item)
|
||||
{
|
||||
this.internalItem = item;
|
||||
}
|
||||
internal GameInventoryItem(InventoryItem item) => this.InternalItem = item;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the this <see cref="GameInventoryItem"/> is empty.
|
||||
/// </summary>
|
||||
public bool IsEmpty => this.InternalItem.ItemID == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the container inventory type.
|
||||
/// </summary>
|
||||
public GameInventoryType ContainerType => (GameInventoryType)this.internalItem.Container;
|
||||
public GameInventoryType ContainerType => (GameInventoryType)this.InternalItem.Container;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the inventory slot index this item is in.
|
||||
/// </summary>
|
||||
public uint InventorySlot => (uint)this.internalItem.Slot;
|
||||
public uint InventorySlot => (uint)this.InternalItem.Slot;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item id.
|
||||
/// </summary>
|
||||
public uint ItemId => this.internalItem.ItemID;
|
||||
public uint ItemId => this.InternalItem.ItemID;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the quantity of items in this item stack.
|
||||
/// </summary>
|
||||
public uint Quantity => this.internalItem.Quantity;
|
||||
public uint Quantity => this.InternalItem.Quantity;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the spiritbond of this item.
|
||||
/// </summary>
|
||||
public uint Spiritbond => this.internalItem.Spiritbond;
|
||||
public uint Spiritbond => this.InternalItem.Spiritbond;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the repair condition of this item.
|
||||
/// </summary>
|
||||
public uint Condition => this.internalItem.Condition;
|
||||
public uint Condition => this.InternalItem.Condition;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the item is High Quality.
|
||||
/// </summary>
|
||||
public bool IsHq => this.internalItem.Flags.HasFlag(InventoryItem.ItemFlags.HQ);
|
||||
public bool IsHq => (this.InternalItem.Flags & InventoryItem.ItemFlags.HQ) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the item has a company crest applied.
|
||||
/// </summary>
|
||||
public bool IsCompanyCrestApplied => this.internalItem.Flags.HasFlag(InventoryItem.ItemFlags.CompanyCrestApplied);
|
||||
|
||||
public bool IsCompanyCrestApplied => (this.InternalItem.Flags & InventoryItem.ItemFlags.CompanyCrestApplied) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the item is a relic.
|
||||
/// </summary>
|
||||
public bool IsRelic => this.internalItem.Flags.HasFlag(InventoryItem.ItemFlags.Relic);
|
||||
public bool IsRelic => (this.InternalItem.Flags & InventoryItem.ItemFlags.Relic) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the is a collectable.
|
||||
/// </summary>
|
||||
public bool IsCollectable => this.internalItem.Flags.HasFlag(InventoryItem.ItemFlags.Collectable);
|
||||
public bool IsCollectable => (this.InternalItem.Flags & InventoryItem.ItemFlags.Collectable) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array of materia types.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<ushort> Materia => new(Unsafe.AsPointer(ref this.internalItem.Materia[0]), 5);
|
||||
public ReadOnlySpan<ushort> Materia => new(Unsafe.AsPointer(ref Unsafe.AsRef(in this.InternalItem.Materia[0])), 5);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array of materia grades.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<ushort> MateriaGrade => new(Unsafe.AsPointer(ref this.internalItem.MateriaGrade[0]), 5);
|
||||
public ReadOnlySpan<ushort> MateriaGrade =>
|
||||
new(Unsafe.AsPointer(ref Unsafe.AsRef(in this.InternalItem.MateriaGrade[0])), 5);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color used for this item.
|
||||
/// </summary>
|
||||
public byte Stain => this.internalItem.Stain;
|
||||
public byte Stain => this.InternalItem.Stain;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the glamour id for this item.
|
||||
/// </summary>
|
||||
public uint GlmaourId => this.internalItem.GlamourID;
|
||||
public uint GlmaourId => this.InternalItem.GlamourID;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items crafter's content id.
|
||||
/// NOTE: I'm not sure if this is a good idea to include or not in the dalamud api. Marked internal for now.
|
||||
/// </summary>
|
||||
internal ulong CrafterContentId => this.internalItem.CrafterContentID;
|
||||
internal ulong CrafterContentId => this.InternalItem.CrafterContentID;
|
||||
|
||||
public static bool operator ==(in GameInventoryItem l, in GameInventoryItem r) => l.Equals(r);
|
||||
|
||||
public static bool operator !=(in GameInventoryItem l, in GameInventoryItem r) => !l.Equals(r);
|
||||
|
||||
/// <inheritdoc/>
|
||||
readonly bool IEquatable<GameInventoryItem>.Equals(GameInventoryItem other) => this.Equals(other);
|
||||
|
||||
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <returns><c>true</c> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <c>false</c>.</returns>
|
||||
public readonly bool Equals(in GameInventoryItem other)
|
||||
{
|
||||
for (var i = 0; i < StructSizeInBytes / 8; i++)
|
||||
{
|
||||
if (this.dataUInt64[i] != other.dataUInt64[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="object.Equals(object?)" />
|
||||
public override bool Equals(object obj) => obj is GameInventoryItem gii && this.Equals(gii);
|
||||
|
||||
/// <inheritdoc cref="object.GetHashCode" />
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var k = 0x5a8447b91aff51b4UL;
|
||||
for (var i = 0; i < StructSizeInBytes / 8; i++)
|
||||
k ^= this.dataUInt64[i];
|
||||
return unchecked((int)(k ^ (k >> 32)));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="object.ToString"/>
|
||||
public override string ToString() =>
|
||||
this.IsEmpty
|
||||
? "<Empty>"
|
||||
: $"Item #{this.ItemId} at slot {this.InventorySlot} in {this.ContainerType}";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue