using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("UnityModdingUtility")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("UnityModdingUtility")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("29730596-8e56-4e1f-ab50-97c3413645fe")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace UnityModdingUtility { public enum AsyncOperationState : byte { NotStarted, InProgress, Complete } public class HandledList : IEnumerable, IEnumerable { private struct Slot { public T Value; public bool Occupied; public void Set(T value) { Value = value; Occupied = true; } public void Clear() { Value = default(T); Occupied = false; } } private readonly int _increment; private Slot[] _slots; public HandledList(int initialSize, int increment) { _slots = new Slot[initialSize]; _increment = increment; } private void expand() { Array.Resize(ref _slots, _slots.Length + _increment); } public int Store(T value) { for (int i = 0; i < _slots.Length; i++) { ref Slot reference = ref _slots[i]; if (!reference.Occupied) { reference.Set(value); return i; } } int num = _slots.Length; expand(); _slots[num].Set(value); return num; } public void Clear(int slotID) { if (slotID < 0 || slotID >= _slots.Length) { throw new ArgumentOutOfRangeException("slotID"); } _slots[slotID].Clear(); } public IEnumerator GetEnumerator() { Slot[] slots = _slots; for (int i = 0; i < slots.Length; i++) { Slot slot = slots[i]; if (slot.Occupied) { yield return slot.Value; } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public class CoroutineOut { public T Result; } public class InitializeAsync { private readonly IUnityCallbackProvider _callbackProvider; private readonly Func, IEnumerator> _coroutineFunc; private CoroutineOut _taskResult; private IEnumerator _coroutine; private int _updateCallbackIndex = -1; private T _result; public AsyncOperationState State { get; private set; } public T Get { get { if (State != AsyncOperationState.Complete) { if (State == AsyncOperationState.NotStarted) { StartAsyncOperation(); } step(forceCompleteThisFrame: true); } return _result; } } public InitializeAsync(IUnityCallbackProvider callbackProvider, Func, IEnumerator> coroutineFunc) { _callbackProvider = callbackProvider; _coroutineFunc = coroutineFunc; State = AsyncOperationState.NotStarted; } public void StartAsyncOperation() { _taskResult = new CoroutineOut(); _coroutine = _coroutineFunc(_taskResult); _updateCallbackIndex = _callbackProvider.RegisterUpdateCallback(update); State = AsyncOperationState.InProgress; } private void update() { if (State == AsyncOperationState.InProgress) { step(forceCompleteThisFrame: false); } } private void step(bool forceCompleteThisFrame) { if (forceCompleteThisFrame) { while (_coroutine.MoveNext()) { } } if (forceCompleteThisFrame || !_coroutine.MoveNext()) { State = AsyncOperationState.Complete; if (_updateCallbackIndex != -1) { _callbackProvider.UnregisterUpdateCallback(_updateCallbackIndex); } _result = _taskResult.Result; } } } public class InitializeOnAccess { private readonly Func _initializeFunc; private T _value; public bool IsInitialized { get; private set; } public T Get { get { if (!IsInitialized) { _value = _initializeFunc(); IsInitialized = true; } return _value; } } public InitializeOnAccess(Func initializeFunc) { _initializeFunc = initializeFunc; IsInitialized = false; } public void Reset() { IsInitialized = false; _value = default(T); } public void SetValue(T value) { _value = value; IsInitialized = true; } public static implicit operator T(InitializeOnAccess initOnAccess) { return initOnAccess.Get; } } public class InitializeOnAccessDictionary : IDictionary, ICollection>, IEnumerable>, IEnumerable, IDictionary, ICollection { public delegate bool ValueSelectorTryGet(TKey key, out TValue value); protected Dictionary _internalDict; private readonly ValueSelectorTryGet _valueSelector; protected object _syncRoot; public virtual TValue this[TKey key] { get { if (TryGetValue(key, out var value)) { return value; } throw new KeyNotFoundException($"Key {key} is not in the dictionary and no value was decided"); } set { _internalDict[key] = value; } } public ICollection Keys => _internalDict.Keys; public ICollection Values => _internalDict.Values; public int Count => _internalDict.Count; public bool IsReadOnly => false; ICollection IDictionary.Keys => _internalDict.Keys; ICollection IDictionary.Values => _internalDict.Values; public bool IsFixedSize => false; public object SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), (object)null); } return _syncRoot; } } public bool IsSynchronized => false; public object this[object key] { get { return this[(TKey)key]; } set { this[(TKey)key] = (TValue)value; } } protected InitializeOnAccessDictionary() { _internalDict = new Dictionary(); } public InitializeOnAccessDictionary(ValueSelectorTryGet selector) : this() { _valueSelector = selector; } public InitializeOnAccessDictionary(Func selector) : this((ValueSelectorTryGet)delegate(TKey key, out TValue value) { value = selector(key); return true; }) { } public InitializeOnAccessDictionary(Func selector) : this((ValueSelectorTryGet)delegate(TKey key, out TValue value) { value = selector(); return true; }) { } public void Add(TKey key, TValue value) { _internalDict.Add(key, value); } public void Clear() { _internalDict.Clear(); } public bool ContainsKey(TKey key) { return _internalDict.ContainsKey(key); } public IEnumerator> GetEnumerator() { return _internalDict.GetEnumerator(); } public bool Remove(TKey key) { return _internalDict.Remove(key); } public virtual bool TryGetValue(TKey key, out TValue value) { if (_internalDict.TryGetValue(key, out value)) { return true; } if (_valueSelector(key, out value)) { _internalDict.Add(key, value); return true; } return false; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void ICollection>.Add(KeyValuePair item) { throw new NotImplementedException(); } bool ICollection>.Contains(KeyValuePair item) { throw new NotImplementedException(); } bool ICollection>.Remove(KeyValuePair item) { throw new NotImplementedException(); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { throw new NotImplementedException(); } public bool Contains(object key) { if (key is TKey key2) { return ContainsKey(key2); } return false; } public void Add(object key, object value) { Add((TKey)key, (TValue)value); } IDictionaryEnumerator IDictionary.GetEnumerator() { return _internalDict.GetEnumerator(); } public void Remove(object key) { Remove((TKey)key); } void ICollection.CopyTo(Array array, int index) { throw new NotImplementedException(); } public void SetTo(IDictionary dict) { _internalDict = new Dictionary(dict); } public static implicit operator Dictionary(InitializeOnAccessDictionary initOnAccessDictionary) { return initOnAccessDictionary._internalDict; } } public class InitializeOnAccessDictionaryArg : InitializeOnAccessDictionary { public delegate bool ValueSelectorTryGetArg(TKey key, TArg arg, out TValue value); private readonly ValueSelectorTryGetArg _valueSelector; public override TValue this[TKey key] => _internalDict[key]; public TValue this[TKey key, TArg arg] { get { if (TryGetValue(key, arg, out var value)) { return value; } throw new KeyNotFoundException($"Key {key} is not in the dictionary and no value was decided"); } set { this[key] = value; } } private InitializeOnAccessDictionaryArg(ValueSelectorTryGet selector) : base(selector) { throw new NotImplementedException(); } public InitializeOnAccessDictionaryArg(ValueSelectorTryGetArg selector) { _valueSelector = selector; } public InitializeOnAccessDictionaryArg(Func selector) : this((ValueSelectorTryGetArg)delegate(TKey key, TArg arg, out TValue value) { value = selector(key, arg); return true; }) { } public InitializeOnAccessDictionaryArg(Func selector) : this((ValueSelectorTryGetArg)delegate(TKey key, TArg arg, out TValue value) { value = selector(arg); return true; }) { } public override bool TryGetValue(TKey key, out TValue value) { return _internalDict.TryGetValue(key, out value); } public bool TryGetValue(TKey key, TArg arg, out TValue value) { if (TryGetValue(key, out value)) { return true; } if (_valueSelector(key, arg, out value)) { _internalDict.Add(key, value); return true; } return false; } public static implicit operator Dictionary(InitializeOnAccessDictionaryArg initOnAccessDictionary) { return initOnAccessDictionary._internalDict; } } public interface IUnityCallbackProvider { int RegisterUpdateCallback(Action update); void UnregisterUpdateCallback(int handle); } } namespace UnityModdingUtility.Extensions { public static class UnityObjectExtensions { public static bool Exists(this Object obj) { if (Object.op_Implicit(obj)) { return obj != (Object)null; } return false; } } }