using System; using Svelto.DataStructures; using Svelto.ECS; namespace TechbloxModdingAPI.Utility { public ref struct OptionalRef where T : struct, IEntityComponent { private readonly State state; private readonly uint index; private NB array; private MB managedArray; private readonly EntityInitializer initializer; //The possible fields are: (index && (array || managedArray)) || initializer public OptionalRef(NB array, uint index) { state = State.Native; this.array = array; this.index = index; initializer = default; } public OptionalRef(MB array, uint index) { state = State.Managed; managedArray = array; this.index = index; initializer = default; this.array = default; } /// /// Wraps the initializer data, if present. /// /// The object with the initializer /// Whether the struct is unmanaged public OptionalRef(EcsObjectBase obj, bool unmanaged) { if (obj.InitData.Valid) { initializer = obj.InitData.Initializer(obj.Id); state = (unmanaged ? State.Native : State.Managed) | State.Initializer; } else { initializer = default; state = State.Empty; } array = default; index = default; } /// /// Returns the value or a default value if empty. Supports objects that are being initialized. /// /// The value or the default value public ref T Get() { CompRefCache.Default = default; //The default value can be changed by mods if (state == State.Empty) return ref CompRefCache.Default; if ((state & State.Initializer) != State.Empty) return ref initializer.GetOrAdd(); if ((state & State.Native) != State.Empty) return ref array[index]; return ref managedArray[index]; } public bool Exists => state != State.Empty; public T? Nullable() => this ? Get() : default; public static implicit operator T(OptionalRef opt) => opt.Get(); public static implicit operator bool(OptionalRef opt) => opt.state != State.Empty; /// /// Creates an instance of a struct T that can be referenced. /// private struct CompRefCache { public static T Default; } /// /// A byte that holds state in its bits. /// [Flags] private enum State : byte { Empty, Native, Managed, Initializer = 4 } } }