namespace Nbt.Tag; public interface INbtValue : INbtTag { object Value { get; set; } } public interface INbtValue : INbtValue where T : notnull { new T Value { get; set; } } public abstract class NbtValue : INbtValue where T : notnull { private static readonly EqualityComparer ValueComparer = EqualityComparer.Default; protected T value; internal protected NbtValue(T value) : base() => this.value = value; public abstract NbtTagType Type { get; } INbtTag INbtTag.this[string tagName] { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } INbtTag INbtTag.this[int tagIndex] { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } INbtTag INbtTag.this[INbtPathElement tagPath] { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } INbtList INbtTag.AsList() => throw new NotSupportedException(); INbtCompound INbtTag.AsCompound() => throw new NotSupportedException(); INbtValue INbtTag.AsValue() => this; INbtValue INbtTag.AsValue() => (INbtValue)this; INbtArray INbtTag.AsArray() => (INbtArray)this; INbtArray INbtTag.AsArray() => (INbtArray)this; INbtTag INbtTag.Copy() => Copy(); public NbtValue Copy() => NewInstance(CopyValue()); object INbtValue.Value { get => Value; set => Value = (T)Convert.ChangeType(value, typeof(T)); } public T Value { get => value; set => this.value = value ?? throw new ArgumentNullException(nameof(value)); } protected virtual T CopyValue() => value; protected abstract NbtValue NewInstance(T value); public bool Equals(INbtTag? other) => ReferenceEquals(other, this) || other is NbtValue o && ValueComparer.Equals(value, o.value); public override bool Equals(object? obj) => ReferenceEquals(obj, this) || obj is NbtValue other && ValueComparer.Equals(value, other.value); public override int GetHashCode() => value.GetHashCode(); }