Dalamud/Dalamud/Utility/ItemUtil.cs
2025-07-26 12:51:20 -07:00

181 lines
5.8 KiB
C#

using System.Runtime.CompilerServices;
using Dalamud.Data;
using Dalamud.Game;
using Dalamud.Game.Text;
using Lumina.Excel.Sheets;
using Lumina.Text;
using Lumina.Text.ReadOnly;
namespace Dalamud.Utility;
/// <summary>
/// Kinds of items that can be fetched from this payload.
/// </summary>
public enum ItemKind : uint
{
/// <summary>
/// Normal items.
/// </summary>
Normal,
/// <summary>
/// Collectible Items.
/// </summary>
Collectible = 500_000,
/// <summary>
/// High-Quality items.
/// </summary>
Hq = 1_000_000,
/// <summary>
/// Event/Key items.
/// </summary>
EventItem = 2_000_000,
}
/// <summary>
/// Utilities related to Items.
/// </summary>
public static class ItemUtil
{
private static int? eventItemRowCount;
/// <summary>Converts raw item ID to item ID with its classification.</summary>
/// <param name="rawItemId">Raw item ID.</param>
/// <returns>Item ID and its classification.</returns>
public static (uint ItemId, ItemKind Kind) GetBaseId(uint rawItemId)
{
if (IsEventItem(rawItemId)) return (rawItemId, ItemKind.EventItem); // EventItem IDs are NOT adjusted
if (IsHighQuality(rawItemId)) return (rawItemId - 1_000_000, ItemKind.Hq);
if (IsCollectible(rawItemId)) return (rawItemId - 500_000, ItemKind.Collectible);
return (rawItemId, ItemKind.Normal);
}
/// <summary>Converts item ID with its classification to raw item ID.</summary>
/// <param name="itemId">Item ID.</param>
/// <param name="kind">Item classification.</param>
/// <returns>Raw Item ID.</returns>
public static uint GetRawId(uint itemId, ItemKind kind)
{
return kind switch
{
ItemKind.Collectible when itemId < 500_000 => itemId + 500_000,
ItemKind.Hq when itemId < 1_000_000 => itemId + 1_000_000,
ItemKind.EventItem => itemId, // EventItem IDs are not adjusted
_ => itemId,
};
}
/// <summary>
/// Checks if the item id belongs to a normal item.
/// </summary>
/// <param name="itemId">The item id to check.</param>
/// <returns><c>true</c> when the item id belongs to a normal item.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNormalItem(uint itemId)
{
return itemId < 500_000;
}
/// <summary>
/// Checks if the item id belongs to a collectible item.
/// </summary>
/// <param name="itemId">The item id to check.</param>
/// <returns><c>true</c> when the item id belongs to a collectible item.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsCollectible(uint itemId)
{
return itemId is >= 500_000 and < 1_000_000;
}
/// <summary>
/// Checks if the item id belongs to a high quality item.
/// </summary>
/// <param name="itemId">The item id to check.</param>
/// <returns><c>true</c> when the item id belongs to a high quality item.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHighQuality(uint itemId)
{
return itemId is >= 1_000_000 and < 2_000_000;
}
/// <summary>
/// Checks if the item id belongs to an event item.
/// </summary>
/// <param name="itemId">The item id to check.</param>
/// <returns><c>true</c> when the item id belongs to an event item.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsEventItem(uint itemId)
{
return itemId >= 2_000_000 && itemId - 2_000_000 < (eventItemRowCount ??= Service<DataManager>.Get().GetExcelSheet<EventItem>().Count);
}
/// <summary>
/// Gets the name of an item.
/// </summary>
/// <param name="itemId">The raw item id.</param>
/// <param name="includeIcon">Whether to include the High Quality or Collectible icon.</param>
/// <param name="language">An optional client language override.</param>
/// <returns>The item name.</returns>
public static ReadOnlySeString GetItemName(uint itemId, bool includeIcon = true, ClientLanguage? language = null)
{
var dataManager = Service<DataManager>.Get();
if (IsEventItem(itemId))
{
return dataManager
.GetExcelSheet<EventItem>(language)
.TryGetRow(itemId, out var eventItem)
? eventItem.Name
: default;
}
var (baseId, kind) = GetBaseId(itemId);
if (!dataManager
.GetExcelSheet<Item>(language)
.TryGetRow(baseId, out var item))
{
return default;
}
if (!includeIcon || kind is not (ItemKind.Hq or ItemKind.Collectible))
return item.Name;
var builder = SeStringBuilder.SharedPool.Get();
builder.Append(item.Name);
switch (kind)
{
case ItemKind.Hq:
builder.Append($" {(char)SeIconChar.HighQuality}");
break;
case ItemKind.Collectible:
builder.Append($" {(char)SeIconChar.Collectible}");
break;
}
var itemName = builder.ToReadOnlySeString();
SeStringBuilder.SharedPool.Return(builder);
return itemName;
}
/// <summary>
/// Gets the color row id for an item name.
/// </summary>
/// <param name="itemId">The raw item Id.</param>
/// <param name="isEdgeColor">Wheather this color is used as edge color.</param>
/// <returns>The Color row id.</returns>
public static uint GetItemRarityColorType(uint itemId, bool isEdgeColor = false)
{
var rarity = 1u;
if (!IsEventItem(itemId) && Service<DataManager>.Get().GetExcelSheet<Item>().TryGetRow(GetBaseId(itemId).ItemId, out var item))
rarity = item.Rarity;
return (isEdgeColor ? 548u : 547u) + (rarity * 2u);
}
}