using Unity.Collections;
using Unity.Entities;
namespace ProjectM.Simulation
{
///
/// One authored item definition, baked immutable into the blob. This is the
/// single source of truth for everything an item IS — resources, tools, weapons, gear, consumables — so
/// adding game content is an authoring row + re-bake, with no code change. Id space is the SAME
/// ushort space as / , and it
/// SUBSUMES the low byte ids (Aether=1/Ore=2/Biomass=3) — a resource is just a
/// low-id item of . KEEP ids 1-3 stable for the existing resources and
/// reserve new item ids > 3; 0 = none. Entity/prefab refs do NOT live here (blobs don't remap entity
/// refs) — a future companion buffer carries those, exactly like AbilityPrefabElement.
///
/// The blob is config (baked identically into both worlds, NOT replicated, NOT in SaveData), so growing
/// this struct later (a granted-ability id, a StatModifier-spec array, a slot id for Phase 1/2/3) is a
/// pure re-bake with zero migration: no SaveData version bump, no ghost-hash change, no desync.
/// is baked NOW because the project's progression axis is gear tiers, so Phase 2/3 tier gating is a
/// content-only edit.
///
public struct ItemDefBlob
{
/// Stable item id (ushort; 1-3 reserved for the existing resources, keep stable for saves).
public ushort ItemId;
/// Broad category (see ), stored as a byte.
public byte Category;
/// Progression tier (0 = base). Higher-tier tools harvest higher-tier nodes / hit harder (Phase 2/3).
public byte Tier;
/// Max units that stack in a single inventory slot (1 for non-stacking equipment).
public int StackMax;
/// Designer-facing display name (shown in the HUD inventory panel).
public FixedString64Bytes Name;
}
///
/// Immutable designer-authored item database, baked from ScriptableObjects to a blob asset and shared by
/// every entity (Burst-fast, zero per-instance cost). Looked up by stable
/// — ID-KEYED, never by array index, so inserting a new item never renumbers existing ids.
///
/// NOTE: the lookup is intentionally NOT a 'readonly' method. A readonly struct method forces a defensive
/// copy of a field when calling a non-readonly member on it; copying a BlobArray breaks its relative-offset
/// pointer, so the array would read as empty. A plain (non-readonly) method accesses the BlobArray in place.
/// Always reach this through 'ref blob.Value' (mirrors ).
///
public struct ItemDatabaseBlob
{
public BlobArray Items;
/// Linear lookup by item id (the array is tiny). Returns false if not present.
public bool TryGetItem(ushort id, out ItemDefBlob def)
{
for (int i = 0; i < Items.Length; i++)
{
if (Items[i].ItemId == id)
{
def = Items[i];
return true;
}
}
def = default;
return false;
}
}
}