using System; using System.Runtime.CompilerServices; using UnityEngine; namespace Jovian.TagSystem { /// /// Lightweight tag identity. 8 bytes, no heap allocation. /// Hierarchy queries are resolved via GameTagManager static lookups. /// [Serializable] public struct JovianTag : IEquatable, IComparable { [SerializeField] private int id; [SerializeField] private int parentId; public int Id => id; public int ParentId => parentId; public JovianTag(int id, int parentId) { this.id = id; this.parentId = parentId; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool IsNone() => id == 0; [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool IsValid() => id > 0; /// /// Checks if this tag is a descendant of the given ancestor. /// Walks the parent chain via GameTagManager. /// public readonly bool IsDescendantOf(JovianTag ancestor) { if(id == 0 || ancestor.id == 0) return false; if(id == ancestor.id) return true; // Walk up from this tag's parent chain var current = this; while(current.parentId != 0) { if(current.parentId == ancestor.id) return true; current = JovianTagsHandler.GetTag(current.parentId); } return false; } /// /// Checks if this tag is an ancestor of the given descendant. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool IsAncestorOf(JovianTag descendant) { return descendant.IsDescendantOf(this); } /// /// Checks if this tag shares the same parent as the given tag. /// public readonly bool IsSiblingTo(JovianTag sibling) { if(id == 0 || sibling.id == 0) return false; return parentId == sibling.parentId; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(JovianTag x, JovianTag y) => x.id == y.id; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(JovianTag x, JovianTag y) => x.id != y.id; [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(JovianTag other) => id == other.id; public readonly int CompareTo(JovianTag other) => id.CompareTo(other.id); public override readonly bool Equals(object obj) => obj is JovianTag other && id == other.id; [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly int GetHashCode() => id; public override readonly string ToString() { if(JovianTagsHandler.IsInitialized) { return JovianTagsHandler.TagToString(this); } return id == 0 ? "None" : $"Tag({id})"; } } }