Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of OCDheim v0.2.0
plugins/UniTask.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
#define UNITY_EDITOR using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Cysharp.Threading.Tasks.CompilerServices; using Cysharp.Threading.Tasks.Internal; using Cysharp.Threading.Tasks.Triggers; using Microsoft.CodeAnalysis; using Unity.Jobs; using UnityEditor; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.LowLevel; using UnityEngine.Networking; using UnityEngine.ParticleSystemJobs; using UnityEngine.PlayerLoop; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("UniTask.Linq")] [assembly: InternalsVisibleTo("UniTask.Addressables")] [assembly: InternalsVisibleTo("UniTask.DOTween")] [assembly: InternalsVisibleTo("UniTask.TextMeshPro")] [assembly: AssemblyVersion("0.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } internal sealed class AsyncMethodBuilderAttribute : Attribute { public Type BuilderType { get; } public AsyncMethodBuilderAttribute(Type builderType) { BuilderType = builderType; } } } namespace Cysharp.Threading.Tasks { public class AsyncLazy { private static Action<object> continuation = SetCompletionSource; private Func<UniTask> taskFactory; private UniTaskCompletionSource completionSource; private UniTask.Awaiter awaiter; private object syncLock; private bool initialized; public UniTask Task { get { EnsureInitialized(); return completionSource.Task; } } public AsyncLazy(Func<UniTask> taskFactory) { this.taskFactory = taskFactory; completionSource = new UniTaskCompletionSource(); syncLock = new object(); initialized = false; } internal AsyncLazy(UniTask task) { taskFactory = null; completionSource = new UniTaskCompletionSource(); syncLock = null; initialized = true; UniTask.Awaiter awaiter = task.GetAwaiter(); if (awaiter.IsCompleted) { SetCompletionSource(in awaiter); return; } this.awaiter = awaiter; awaiter.SourceOnCompleted(continuation, this); } public UniTask.Awaiter GetAwaiter() { return Task.GetAwaiter(); } private void EnsureInitialized() { if (!Volatile.Read(ref initialized)) { EnsureInitializedCore(); } } private void EnsureInitializedCore() { lock (syncLock) { if (Volatile.Read(ref initialized)) { return; } Func<UniTask> func = Interlocked.Exchange(ref taskFactory, null); if (func != null) { UniTask.Awaiter awaiter = func().GetAwaiter(); if (awaiter.IsCompleted) { SetCompletionSource(in awaiter); } else { this.awaiter = awaiter; awaiter.SourceOnCompleted(continuation, this); } Volatile.Write(ref initialized, value: true); } } } private void SetCompletionSource(in UniTask.Awaiter awaiter) { try { awaiter.GetResult(); completionSource.TrySetResult(); } catch (Exception exception) { completionSource.TrySetException(exception); } } private static void SetCompletionSource(object state) { AsyncLazy asyncLazy = (AsyncLazy)state; try { asyncLazy.awaiter.GetResult(); asyncLazy.completionSource.TrySetResult(); } catch (Exception exception) { asyncLazy.completionSource.TrySetException(exception); } finally { asyncLazy.awaiter = default(UniTask.Awaiter); } } } public class AsyncLazy<T> { private static Action<object> continuation = SetCompletionSource; private Func<UniTask<T>> taskFactory; private UniTaskCompletionSource<T> completionSource; private UniTask<T>.Awaiter awaiter; private object syncLock; private bool initialized; public UniTask<T> Task { get { EnsureInitialized(); return completionSource.Task; } } public AsyncLazy(Func<UniTask<T>> taskFactory) { this.taskFactory = taskFactory; completionSource = new UniTaskCompletionSource<T>(); syncLock = new object(); initialized = false; } internal AsyncLazy(UniTask<T> task) { taskFactory = null; completionSource = new UniTaskCompletionSource<T>(); syncLock = null; initialized = true; UniTask<T>.Awaiter awaiter = task.GetAwaiter(); if (awaiter.IsCompleted) { SetCompletionSource(in awaiter); return; } this.awaiter = awaiter; awaiter.SourceOnCompleted(continuation, this); } public UniTask<T>.Awaiter GetAwaiter() { return Task.GetAwaiter(); } private void EnsureInitialized() { if (!Volatile.Read(ref initialized)) { EnsureInitializedCore(); } } private void EnsureInitializedCore() { lock (syncLock) { if (Volatile.Read(ref initialized)) { return; } Func<UniTask<T>> func = Interlocked.Exchange(ref taskFactory, null); if (func != null) { UniTask<T>.Awaiter awaiter = func().GetAwaiter(); if (awaiter.IsCompleted) { SetCompletionSource(in awaiter); } else { this.awaiter = awaiter; awaiter.SourceOnCompleted(continuation, this); } Volatile.Write(ref initialized, value: true); } } } private void SetCompletionSource(in UniTask<T>.Awaiter awaiter) { try { T result = awaiter.GetResult(); completionSource.TrySetResult(result); } catch (Exception exception) { completionSource.TrySetException(exception); } } private static void SetCompletionSource(object state) { AsyncLazy<T> asyncLazy = (AsyncLazy<T>)state; try { T result = asyncLazy.awaiter.GetResult(); asyncLazy.completionSource.TrySetResult(result); } catch (Exception exception) { asyncLazy.completionSource.TrySetException(exception); } finally { asyncLazy.awaiter = default(UniTask<T>.Awaiter); } } } public interface IReadOnlyAsyncReactiveProperty<T> : IUniTaskAsyncEnumerable<T> { T Value { get; } IUniTaskAsyncEnumerable<T> WithoutCurrent(); UniTask<T> WaitAsync(CancellationToken cancellationToken = default(CancellationToken)); } public interface IAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>, IUniTaskAsyncEnumerable<T> { new T Value { get; set; } } [Serializable] public class AsyncReactiveProperty<T> : IAsyncReactiveProperty<T>, IReadOnlyAsyncReactiveProperty<T>, IUniTaskAsyncEnumerable<T>, IDisposable { private sealed class WaitAsyncSource : IUniTaskSource<T>, IUniTaskSource, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource> { private static Action<object> cancellationCallback; private static TaskPool<WaitAsyncSource> pool; private WaitAsyncSource nextNode; private AsyncReactiveProperty<T> parent; private CancellationToken cancellationToken; private CancellationTokenRegistration cancellationTokenRegistration; private UniTaskCompletionSourceCore<T> core; ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode; ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; } ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; } static WaitAsyncSource() { cancellationCallback = CancellationCallback; TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size); } private WaitAsyncSource() { } public static IUniTaskSource<T> Create(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token) { if (cancellationToken.IsCancellationRequested) { return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token); } if (!pool.TryPop(out var result)) { result = new WaitAsyncSource(); } result.parent = parent; result.cancellationToken = cancellationToken; if (cancellationToken.CanBeCanceled) { result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result); } result.parent.triggerEvent.Add(result); TaskTracker.TrackActiveTask(result, 3); token = result.core.Version; return result; } private bool TryReturn() { TaskTracker.RemoveTracking(this); core.Reset(); cancellationTokenRegistration.Dispose(); cancellationTokenRegistration = default(CancellationTokenRegistration); parent.triggerEvent.Remove(this); parent = null; cancellationToken = default(CancellationToken); return pool.TryPush(this); } private static void CancellationCallback(object state) { WaitAsyncSource obj = (WaitAsyncSource)state; obj.OnCanceled(obj.cancellationToken); } public T GetResult(short token) { try { return core.GetResult(token); } finally { TryReturn(); } } void IUniTaskSource.GetResult(short token) { GetResult(token); } public void OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } public void OnCanceled(CancellationToken cancellationToken) { core.TrySetCanceled(cancellationToken); } public void OnCompleted() { core.TrySetCanceled(CancellationToken.None); } public void OnError(Exception ex) { core.TrySetException(ex); } public void OnNext(T value) { core.TrySetResult(value); } } private sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T> { private readonly AsyncReactiveProperty<T> parent; public WithoutCurrentEnumerable(AsyncReactiveProperty<T> parent) { this.parent = parent; } public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)) { return new Enumerator(parent, cancellationToken, publishCurrentValue: false); } } private sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, IUniTaskAsyncDisposable, ITriggerHandler<T> { private static Action<object> cancellationCallback = CancellationCallback; private readonly AsyncReactiveProperty<T> parent; private readonly CancellationToken cancellationToken; private readonly CancellationTokenRegistration cancellationTokenRegistration; private T value; private bool isDisposed; private bool firstCall; public T Current => value; ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; } ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; } public Enumerator(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue) { this.parent = parent; this.cancellationToken = cancellationToken; firstCall = publishCurrentValue; parent.triggerEvent.Add(this); TaskTracker.TrackActiveTask(this, 3); if (cancellationToken.CanBeCanceled) { cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this); } } public UniTask<bool> MoveNextAsync() { if (firstCall) { firstCall = false; value = parent.Value; return CompletedTasks.True; } completionSource.Reset(); return new UniTask<bool>(this, completionSource.Version); } public UniTask DisposeAsync() { if (!isDisposed) { isDisposed = true; TaskTracker.RemoveTracking(this); completionSource.TrySetCanceled(cancellationToken); parent.triggerEvent.Remove(this); } return default(UniTask); } public void OnNext(T value) { this.value = value; completionSource.TrySetResult(result: true); } public void OnCanceled(CancellationToken cancellationToken) { DisposeAsync().Forget(); } public void OnCompleted() { completionSource.TrySetResult(result: false); } public void OnError(Exception ex) { completionSource.TrySetException(ex); } private static void CancellationCallback(object state) { ((Enumerator)state).DisposeAsync().Forget(); } } private TriggerEvent<T> triggerEvent; [SerializeField] private T latestValue; private static bool isValueType; public T Value { get { return latestValue; } set { latestValue = value; triggerEvent.SetResult(value); } } public AsyncReactiveProperty(T value) { latestValue = value; triggerEvent = default(TriggerEvent<T>); } public IUniTaskAsyncEnumerable<T> WithoutCurrent() { return new WithoutCurrentEnumerable(this); } public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken) { return new Enumerator(this, cancellationToken, publishCurrentValue: true); } public void Dispose() { triggerEvent.SetCompleted(); } public static implicit operator T(AsyncReactiveProperty<T> value) { return value.Value; } public override string ToString() { if (isValueType) { return latestValue.ToString(); } return latestValue?.ToString(); } public UniTask<T> WaitAsync(CancellationToken cancellationToken = default(CancellationToken)) { short token; return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out token), token); } static AsyncReactiveProperty() { isValueType = typeof(T).IsValueType; } } public class ReadOnlyAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>, IUniTaskAsyncEnumerable<T>, IDisposable { private sealed class WaitAsyncSource : IUniTaskSource<T>, IUniTaskSource, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource> { private static Action<object> cancellationCallback; private static TaskPool<WaitAsyncSource> pool; private WaitAsyncSource nextNode; private ReadOnlyAsyncReactiveProperty<T> parent; private CancellationToken cancellationToken; private CancellationTokenRegistration cancellationTokenRegistration; private UniTaskCompletionSourceCore<T> core; ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode; ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; } ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; } static WaitAsyncSource() { cancellationCallback = CancellationCallback; TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size); } private WaitAsyncSource() { } public static IUniTaskSource<T> Create(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token) { if (cancellationToken.IsCancellationRequested) { return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token); } if (!pool.TryPop(out var result)) { result = new WaitAsyncSource(); } result.parent = parent; result.cancellationToken = cancellationToken; if (cancellationToken.CanBeCanceled) { result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result); } result.parent.triggerEvent.Add(result); TaskTracker.TrackActiveTask(result, 3); token = result.core.Version; return result; } private bool TryReturn() { TaskTracker.RemoveTracking(this); core.Reset(); cancellationTokenRegistration.Dispose(); cancellationTokenRegistration = default(CancellationTokenRegistration); parent.triggerEvent.Remove(this); parent = null; cancellationToken = default(CancellationToken); return pool.TryPush(this); } private static void CancellationCallback(object state) { WaitAsyncSource obj = (WaitAsyncSource)state; obj.OnCanceled(obj.cancellationToken); } public T GetResult(short token) { try { return core.GetResult(token); } finally { TryReturn(); } } void IUniTaskSource.GetResult(short token) { GetResult(token); } public void OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } public void OnCanceled(CancellationToken cancellationToken) { core.TrySetCanceled(cancellationToken); } public void OnCompleted() { core.TrySetCanceled(CancellationToken.None); } public void OnError(Exception ex) { core.TrySetException(ex); } public void OnNext(T value) { core.TrySetResult(value); } } private sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T> { private readonly ReadOnlyAsyncReactiveProperty<T> parent; public WithoutCurrentEnumerable(ReadOnlyAsyncReactiveProperty<T> parent) { this.parent = parent; } public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)) { return new Enumerator(parent, cancellationToken, publishCurrentValue: false); } } private sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, IUniTaskAsyncDisposable, ITriggerHandler<T> { private static Action<object> cancellationCallback = CancellationCallback; private readonly ReadOnlyAsyncReactiveProperty<T> parent; private readonly CancellationToken cancellationToken; private readonly CancellationTokenRegistration cancellationTokenRegistration; private T value; private bool isDisposed; private bool firstCall; public T Current => value; ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; } ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; } public Enumerator(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue) { this.parent = parent; this.cancellationToken = cancellationToken; firstCall = publishCurrentValue; parent.triggerEvent.Add(this); TaskTracker.TrackActiveTask(this, 3); if (cancellationToken.CanBeCanceled) { cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this); } } public UniTask<bool> MoveNextAsync() { if (firstCall) { firstCall = false; value = parent.Value; return CompletedTasks.True; } completionSource.Reset(); return new UniTask<bool>(this, completionSource.Version); } public UniTask DisposeAsync() { if (!isDisposed) { isDisposed = true; TaskTracker.RemoveTracking(this); completionSource.TrySetCanceled(cancellationToken); parent.triggerEvent.Remove(this); } return default(UniTask); } public void OnNext(T value) { this.value = value; completionSource.TrySetResult(result: true); } public void OnCanceled(CancellationToken cancellationToken) { DisposeAsync().Forget(); } public void OnCompleted() { completionSource.TrySetResult(result: false); } public void OnError(Exception ex) { completionSource.TrySetException(ex); } private static void CancellationCallback(object state) { ((Enumerator)state).DisposeAsync().Forget(); } } private TriggerEvent<T> triggerEvent; private T latestValue; private IUniTaskAsyncEnumerator<T> enumerator; private static bool isValueType; public T Value => latestValue; public ReadOnlyAsyncReactiveProperty(T initialValue, IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken) { latestValue = initialValue; ConsumeEnumerator(source, cancellationToken).Forget(); } public ReadOnlyAsyncReactiveProperty(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken) { ConsumeEnumerator(source, cancellationToken).Forget(); } private async UniTaskVoid ConsumeEnumerator(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken) { enumerator = source.GetAsyncEnumerator(cancellationToken); try { while (await enumerator.MoveNextAsync()) { T result = (latestValue = enumerator.Current); triggerEvent.SetResult(result); } } finally { await enumerator.DisposeAsync(); enumerator = null; } } public IUniTaskAsyncEnumerable<T> WithoutCurrent() { return new WithoutCurrentEnumerable(this); } public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken) { return new Enumerator(this, cancellationToken, publishCurrentValue: true); } public void Dispose() { if (enumerator != null) { enumerator.DisposeAsync().Forget(); } triggerEvent.SetCompleted(); } public static implicit operator T(ReadOnlyAsyncReactiveProperty<T> value) { return value.Value; } public override string ToString() { if (isValueType) { return latestValue.ToString(); } return latestValue?.ToString(); } public UniTask<T> WaitAsync(CancellationToken cancellationToken = default(CancellationToken)) { short token; return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out token), token); } static ReadOnlyAsyncReactiveProperty() { isValueType = typeof(T).IsValueType; } } public static class StateExtensions { public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken) { return new ReadOnlyAsyncReactiveProperty<T>(source, cancellationToken); } public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, T initialValue, CancellationToken cancellationToken) { return new ReadOnlyAsyncReactiveProperty<T>(initialValue, source, cancellationToken); } } [StructLayout(LayoutKind.Sequential, Size = 1)] public readonly struct AsyncUnit : IEquatable<AsyncUnit> { public static readonly AsyncUnit Default; public override int GetHashCode() { return 0; } public bool Equals(AsyncUnit other) { return true; } public override string ToString() { return "()"; } } public class CancellationTokenEqualityComparer : IEqualityComparer<CancellationToken> { public static readonly IEqualityComparer<CancellationToken> Default = new CancellationTokenEqualityComparer(); public bool Equals(CancellationToken x, CancellationToken y) { return x.Equals(y); } public int GetHashCode(CancellationToken obj) { return obj.GetHashCode(); } } public static class CancellationTokenExtensions { private static readonly Action<object> cancellationTokenCallback = Callback; private static readonly Action<object> disposeCallback = DisposeCallback; public static CancellationToken ToCancellationToken(this UniTask task) { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); ToCancellationTokenCore(task, cancellationTokenSource).Forget(); return cancellationTokenSource.Token; } public static CancellationToken ToCancellationToken(this UniTask task, CancellationToken linkToken) { if (linkToken.IsCancellationRequested) { return linkToken; } if (!linkToken.CanBeCanceled) { return task.ToCancellationToken(); } CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(new CancellationToken[1] { linkToken }); ToCancellationTokenCore(task, cancellationTokenSource).Forget(); return cancellationTokenSource.Token; } public static CancellationToken ToCancellationToken<T>(this UniTask<T> task) { return task.AsUniTask().ToCancellationToken(); } public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken) { return task.AsUniTask().ToCancellationToken(linkToken); } private static async UniTaskVoid ToCancellationTokenCore(UniTask task, CancellationTokenSource cts) { try { await task; } catch (Exception ex) { UniTaskScheduler.PublishUnobservedTaskException(ex); } cts.Cancel(); cts.Dispose(); } public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return (UniTask.FromCanceled(cancellationToken), default(CancellationTokenRegistration)); } UniTaskCompletionSource uniTaskCompletionSource = new UniTaskCompletionSource(); return (uniTaskCompletionSource.Task, cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, uniTaskCompletionSource)); } private static void Callback(object state) { ((UniTaskCompletionSource)state).TrySetResult(); } public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken) { return new CancellationTokenAwaitable(cancellationToken); } public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback) { bool flag = false; if (!ExecutionContext.IsFlowSuppressed()) { ExecutionContext.SuppressFlow(); flag = true; } try { return cancellationToken.Register(callback, useSynchronizationContext: false); } finally { if (flag) { ExecutionContext.RestoreFlow(); } } } public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action<object> callback, object state) { bool flag = false; if (!ExecutionContext.IsFlowSuppressed()) { ExecutionContext.SuppressFlow(); flag = true; } try { return cancellationToken.Register(callback, state, useSynchronizationContext: false); } finally { if (flag) { ExecutionContext.RestoreFlow(); } } } public static CancellationTokenRegistration AddTo(this IDisposable disposable, CancellationToken cancellationToken) { return cancellationToken.RegisterWithoutCaptureExecutionContext(disposeCallback, disposable); } private static void DisposeCallback(object state) { ((IDisposable)state).Dispose(); } } public struct CancellationTokenAwaitable { public struct Awaiter : ICriticalNotifyCompletion, INotifyCompletion { private CancellationToken cancellationToken; public bool IsCompleted { get { if (cancellationToken.CanBeCanceled) { return cancellationToken.IsCancellationRequested; } return true; } } public Awaiter(CancellationToken cancellationToken) { this.cancellationToken = cancellationToken; } public void GetResult() { } public void OnCompleted(Action continuation) { UnsafeOnCompleted(continuation); } public void UnsafeOnCompleted(Action continuation) { cancellationToken.RegisterWithoutCaptureExecutionContext(continuation); } } private CancellationToken cancellationToken; public CancellationTokenAwaitable(CancellationToken cancellationToken) { this.cancellationToken = cancellationToken; } public Awaiter GetAwaiter() { return new Awaiter(cancellationToken); } } public static class CancellationTokenSourceExtensions { private static readonly Action<object> CancelCancellationTokenSourceStateDelegate = CancelCancellationTokenSourceState; private static void CancelCancellationTokenSourceState(object state) { ((CancellationTokenSource)state).Cancel(); } public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update) { return cts.CancelAfterSlim(TimeSpan.FromMilliseconds(millisecondsDelay), delayType, delayTiming); } public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update) { return PlayerLoopTimer.StartNew(delayTimeSpan, periodic: false, delayType, delayTiming, cts.Token, CancelCancellationTokenSourceStateDelegate, cts); } public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component) { cts.RegisterRaiseCancelOnDestroy(component.gameObject); } public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject) { gameObject.GetAsyncDestroyTrigger().CancellationToken.RegisterWithoutCaptureExecutionContext(CancelCancellationTokenSourceStateDelegate, cts); } } public static class Channel { public static Channel<T> CreateSingleConsumerUnbounded<T>() { return new SingleConsumerUnboundedChannel<T>(); } } public abstract class Channel<TWrite, TRead> { public ChannelReader<TRead> Reader { get; protected set; } public ChannelWriter<TWrite> Writer { get; protected set; } public static implicit operator ChannelReader<TRead>(Channel<TWrite, TRead> channel) { return channel.Reader; } public static implicit operator ChannelWriter<TWrite>(Channel<TWrite, TRead> channel) { return channel.Writer; } } public abstract class Channel<T> : Channel<T, T> { } public abstract class ChannelReader<T> { public abstract UniTask Completion { get; } public abstract bool TryRead(out T item); public abstract UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken = default(CancellationToken)); public virtual UniTask<T> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TryRead(out var item)) { return UniTask.FromResult(item); } return ReadAsyncCore(cancellationToken); } private async UniTask<T> ReadAsyncCore(CancellationToken cancellationToken = default(CancellationToken)) { if (await WaitToReadAsync(cancellationToken) && TryRead(out var item)) { return item; } throw new ChannelClosedException(); } public abstract IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default(CancellationToken)); } public abstract class ChannelWriter<T> { public abstract bool TryWrite(T item); public abstract bool TryComplete(Exception error = null); public void Complete(Exception error = null) { if (!TryComplete(error)) { throw new ChannelClosedException(); } } } public class ChannelClosedException : InvalidOperationException { public ChannelClosedException() : base("Channel is already closed.") { } public ChannelClosedException(string message) : base(message) { } public ChannelClosedException(Exception innerException) : base("Channel is already closed", innerException) { } public ChannelClosedException(string message, Exception innerException) : base(message, innerException) { } } internal class SingleConsumerUnboundedChannel<T> : Channel<T> { private sealed class SingleConsumerUnboundedChannelWriter : ChannelWriter<T> { private readonly SingleConsumerUnboundedChannel<T> parent; public SingleConsumerUnboundedChannelWriter(SingleConsumerUnboundedChannel<T> parent) { this.parent = parent; } public override bool TryWrite(T item) { bool isWaiting; lock (parent.items) { if (parent.closed) { return false; } parent.items.Enqueue(item); isWaiting = parent.readerSource.isWaiting; } if (isWaiting) { parent.readerSource.SingalContinuation(); } return true; } public override bool TryComplete(Exception error = null) { lock (parent.items) { if (parent.closed) { return false; } parent.closed = true; bool isWaiting = parent.readerSource.isWaiting; if (parent.items.Count == 0) { if (error == null) { if (parent.completedTaskSource != null) { parent.completedTaskSource.TrySetResult(); } else { parent.completedTask = UniTask.CompletedTask; } } else if (parent.completedTaskSource != null) { parent.completedTaskSource.TrySetException(error); } else { parent.completedTask = UniTask.FromException(error); } if (isWaiting) { parent.readerSource.SingalCompleted(error); } } parent.completionError = error; } return true; } } private sealed class SingleConsumerUnboundedChannelReader : ChannelReader<T>, IUniTaskSource<bool>, IUniTaskSource { private sealed class ReadAllAsyncEnumerable : IUniTaskAsyncEnumerable<T>, IUniTaskAsyncEnumerator<T>, IUniTaskAsyncDisposable { private readonly Action<object> CancellationCallback1Delegate = CancellationCallback1; private readonly Action<object> CancellationCallback2Delegate = CancellationCallback2; private readonly SingleConsumerUnboundedChannelReader parent; private CancellationToken cancellationToken1; private CancellationToken cancellationToken2; private CancellationTokenRegistration cancellationTokenRegistration1; private CancellationTokenRegistration cancellationTokenRegistration2; private T current; private bool cacheValue; private bool running; public T Current { get { if (cacheValue) { return current; } parent.TryRead(out current); return current; } } public ReadAllAsyncEnumerable(SingleConsumerUnboundedChannelReader parent, CancellationToken cancellationToken) { this.parent = parent; cancellationToken1 = cancellationToken; } public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)) { if (running) { throw new InvalidOperationException("Enumerator is already running, does not allow call GetAsyncEnumerator twice."); } if (cancellationToken1 != cancellationToken) { cancellationToken2 = cancellationToken; } if (cancellationToken1.CanBeCanceled) { cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancellationCallback1Delegate, this); } if (cancellationToken2.CanBeCanceled) { cancellationTokenRegistration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(CancellationCallback2Delegate, this); } running = true; return this; } public UniTask<bool> MoveNextAsync() { cacheValue = false; return parent.WaitToReadAsync(CancellationToken.None); } public UniTask DisposeAsync() { cancellationTokenRegistration1.Dispose(); cancellationTokenRegistration2.Dispose(); return default(UniTask); } private static void CancellationCallback1(object state) { ReadAllAsyncEnumerable readAllAsyncEnumerable = (ReadAllAsyncEnumerable)state; readAllAsyncEnumerable.parent.SingalCancellation(readAllAsyncEnumerable.cancellationToken1); } private static void CancellationCallback2(object state) { ReadAllAsyncEnumerable readAllAsyncEnumerable = (ReadAllAsyncEnumerable)state; readAllAsyncEnumerable.parent.SingalCancellation(readAllAsyncEnumerable.cancellationToken2); } } private readonly Action<object> CancellationCallbackDelegate = CancellationCallback; private readonly SingleConsumerUnboundedChannel<T> parent; private CancellationToken cancellationToken; private CancellationTokenRegistration cancellationTokenRegistration; private UniTaskCompletionSourceCore<bool> core; internal bool isWaiting; public override UniTask Completion { get { if (parent.completedTaskSource != null) { return parent.completedTaskSource.Task; } if (parent.closed) { return parent.completedTask; } parent.completedTaskSource = new UniTaskCompletionSource(); return parent.completedTaskSource.Task; } } public SingleConsumerUnboundedChannelReader(SingleConsumerUnboundedChannel<T> parent) { this.parent = parent; TaskTracker.TrackActiveTask(this, 4); } public override bool TryRead(out T item) { lock (parent.items) { if (parent.items.Count == 0) { item = default(T); return false; } item = parent.items.Dequeue(); if (parent.closed && parent.items.Count == 0) { if (parent.completionError != null) { if (parent.completedTaskSource != null) { parent.completedTaskSource.TrySetException(parent.completionError); } else { parent.completedTask = UniTask.FromException(parent.completionError); } } else if (parent.completedTaskSource != null) { parent.completedTaskSource.TrySetResult(); } else { parent.completedTask = UniTask.CompletedTask; } } } return true; } public override UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return UniTask.FromCanceled<bool>(cancellationToken); } lock (parent.items) { if (parent.items.Count != 0) { return CompletedTasks.True; } if (parent.closed) { if (parent.completionError == null) { return CompletedTasks.False; } return UniTask.FromException<bool>(parent.completionError); } cancellationTokenRegistration.Dispose(); core.Reset(); isWaiting = true; this.cancellationToken = cancellationToken; if (this.cancellationToken.CanBeCanceled) { cancellationTokenRegistration = this.cancellationToken.RegisterWithoutCaptureExecutionContext(CancellationCallbackDelegate, this); } return new UniTask<bool>(this, core.Version); } } public void SingalContinuation() { core.TrySetResult(result: true); } public void SingalCancellation(CancellationToken cancellationToken) { TaskTracker.RemoveTracking(this); core.TrySetCanceled(cancellationToken); } public void SingalCompleted(Exception error) { if (error != null) { TaskTracker.RemoveTracking(this); core.TrySetException(error); } else { TaskTracker.RemoveTracking(this); core.TrySetResult(result: false); } } public override IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default(CancellationToken)) { return new ReadAllAsyncEnumerable(this, cancellationToken); } bool IUniTaskSource<bool>.GetResult(short token) { return core.GetResult(token); } void IUniTaskSource.GetResult(short token) { core.GetResult(token); } UniTaskStatus IUniTaskSource.GetStatus(short token) { return core.GetStatus(token); } void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } UniTaskStatus IUniTaskSource.UnsafeGetStatus() { return core.UnsafeGetStatus(); } private static void CancellationCallback(object state) { SingleConsumerUnboundedChannelReader obj = (SingleConsumerUnboundedChannelReader)state; obj.SingalCancellation(obj.cancellationToken); } } private readonly Queue<T> items; private readonly SingleConsumerUnboundedChannelReader readerSource; private UniTaskCompletionSource completedTaskSource; private UniTask completedTask; private Exception completionError; private bool closed; public SingleConsumerUnboundedChannel() { items = new Queue<T>(); base.Writer = new SingleConsumerUnboundedChannelWriter(this); readerSource = new SingleConsumerUnboundedChannelReader(this); base.Reader = readerSource; } } public static class EnumerableAsyncExtensions { public static IEnumerable<UniTask> Select<T>(this IEnumerable<T> source, Func<T, UniTask> selector) { return Enumerable.Select(source, selector); } public static IEnumerable<UniTask<TR>> Select<T, TR>(this IEnumerable<T> source, Func<T, UniTask<TR>> selector) { return Enumerable.Select(source, selector); } public static IEnumerable<UniTask> Select<T>(this IEnumerable<T> source, Func<T, int, UniTask> selector) { return Enumerable.Select(source, selector); } public static IEnumerable<UniTask<TR>> Select<T, TR>(this IEnumerable<T> source, Func<T, int, UniTask<TR>> selector) { return Enumerable.Select(source, selector); } } public static class EnumeratorAsyncExtensions { private sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise> { private static TaskPool<EnumeratorPromise> pool; private EnumeratorPromise nextNode; private IEnumerator innerEnumerator; private CancellationToken cancellationToken; private int initialFrame; private bool loopRunning; private bool calledGetResult; private UniTaskCompletionSourceCore<object> core; private static readonly FieldInfo waitForSeconds_Seconds; public ref EnumeratorPromise NextNode => ref nextNode; static EnumeratorPromise() { waitForSeconds_Seconds = typeof(WaitForSeconds).GetField("m_Seconds", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); TaskPool.RegisterSizeGetter(typeof(EnumeratorPromise), () => pool.Size); } private EnumeratorPromise() { } public static IUniTaskSource Create(IEnumerator innerEnumerator, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token) { if (cancellationToken.IsCancellationRequested) { return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } if (!pool.TryPop(out var result)) { result = new EnumeratorPromise(); } TaskTracker.TrackActiveTask(result, 3); result.innerEnumerator = ConsumeEnumerator(innerEnumerator); result.cancellationToken = cancellationToken; result.loopRunning = true; result.calledGetResult = false; result.initialFrame = -1; token = result.core.Version; if (result.MoveNext()) { PlayerLoopHelper.AddAction(timing, result); } return result; } public void GetResult(short token) { try { calledGetResult = true; core.GetResult(token); } finally { if (!loopRunning) { TryReturn(); } } } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } public void OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public bool MoveNext() { if (calledGetResult) { loopRunning = false; TryReturn(); return false; } if (innerEnumerator == null) { return false; } if (cancellationToken.IsCancellationRequested) { loopRunning = false; core.TrySetCanceled(cancellationToken); return false; } if (initialFrame == -1) { if (PlayerLoopHelper.IsMainThread) { initialFrame = Time.frameCount; } } else if (initialFrame == Time.frameCount) { return true; } try { if (innerEnumerator.MoveNext()) { return true; } } catch (Exception error) { loopRunning = false; core.TrySetException(error); return false; } loopRunning = false; core.TrySetResult(null); return false; } private bool TryReturn() { TaskTracker.RemoveTracking(this); core.Reset(); innerEnumerator = null; cancellationToken = default(CancellationToken); return pool.TryPush(this); } private static IEnumerator ConsumeEnumerator(IEnumerator enumerator) { while (enumerator.MoveNext()) { object current = enumerator.Current; if (current == null) { yield return null; continue; } CustomYieldInstruction cyi = (CustomYieldInstruction)((current is CustomYieldInstruction) ? current : null); if (cyi != null) { while (cyi.keepWaiting) { yield return null; } continue; } if (current is YieldInstruction) { IEnumerator innerCoroutine2 = null; AsyncOperation val = (AsyncOperation)((current is AsyncOperation) ? current : null); if (val == null) { WaitForSeconds val2 = (WaitForSeconds)((current is WaitForSeconds) ? current : null); if (val2 != null) { innerCoroutine2 = UnwrapWaitForSeconds(val2); } } else { innerCoroutine2 = UnwrapWaitAsyncOperation(val); } if (innerCoroutine2 != null) { while (innerCoroutine2.MoveNext()) { yield return null; } continue; } } else if (current is IEnumerator enumerator2) { IEnumerator innerCoroutine2 = ConsumeEnumerator(enumerator2); while (innerCoroutine2.MoveNext()) { yield return null; } continue; } Debug.LogWarning((object)("yield " + current.GetType().Name + " is not supported on await IEnumerator or IEnumerator.ToUniTask(), please use ToUniTask(MonoBehaviour coroutineRunner) instead.")); yield return null; } } private static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds) { float second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds); float elapsed = 0f; do { yield return null; elapsed += Time.deltaTime; } while (!(elapsed >= second)); } private static IEnumerator UnwrapWaitAsyncOperation(AsyncOperation asyncOperation) { while (!asyncOperation.isDone) { yield return null; } } } public static UniTask.Awaiter GetAwaiter<T>(this T enumerator) where T : IEnumerator { object obj = enumerator; Error.ThrowArgumentNullException((IEnumerator)obj, "enumerator"); short token; return new UniTask(EnumeratorPromise.Create((IEnumerator)obj, PlayerLoopTiming.Update, CancellationToken.None, out token), token).GetAwaiter(); } public static UniTask WithCancellation(this IEnumerator enumerator, CancellationToken cancellationToken) { Error.ThrowArgumentNullException(enumerator, "enumerator"); short token; return new UniTask(EnumeratorPromise.Create(enumerator, PlayerLoopTiming.Update, cancellationToken, out token), token); } public static UniTask ToUniTask(this IEnumerator enumerator, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken)) { Error.ThrowArgumentNullException(enumerator, "enumerator"); short token; return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out token), token); } public static UniTask ToUniTask(this IEnumerator enumerator, MonoBehaviour coroutineRunner) { AutoResetUniTaskCompletionSource autoResetUniTaskCompletionSource = AutoResetUniTaskCompletionSource.Create(); coroutineRunner.StartCoroutine(Core(enumerator, coroutineRunner, autoResetUniTaskCompletionSource)); return autoResetUniTaskCompletionSource.Task; } private static IEnumerator Core(IEnumerator inner, MonoBehaviour coroutineRunner, AutoResetUniTaskCompletionSource source) { yield return coroutineRunner.StartCoroutine(inner); source.TrySetResult(); } } public static class ExceptionExtensions { public static bool IsOperationCanceledException(this Exception exception) { return exception is OperationCanceledException; } } public interface IUniTaskAsyncEnumerable<out T> { IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default(CancellationToken)); } public interface IUniTaskAsyncEnumerator<out T> : IUniTaskAsyncDisposable { T Current { get; } UniTask<bool> MoveNextAsync(); } public interface IUniTaskAsyncDisposable { UniTask DisposeAsync(); } public interface IUniTaskOrderedAsyncEnumerable<TElement> : IUniTaskAsyncEnumerable<TElement> { IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending); IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending); IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending); } public interface IConnectableUniTaskAsyncEnumerable<out T> : IUniTaskAsyncEnumerable<T> { IDisposable Connect(); } public static class UniTaskAsyncEnumerableExtensions { public static UniTaskCancelableAsyncEnumerable<T> WithCancellation<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken) { return new UniTaskCancelableAsyncEnumerable<T>(source, cancellationToken); } } [StructLayout(LayoutKind.Auto)] public readonly struct UniTaskCancelableAsyncEnumerable<T> { [StructLayout(LayoutKind.Auto)] public readonly struct Enumerator { private readonly IUniTaskAsyncEnumerator<T> enumerator; public T Current => enumerator.Current; internal Enumerator(IUniTaskAsyncEnumerator<T> enumerator) { this.enumerator = enumerator; } public UniTask<bool> MoveNextAsync() { return enumerator.MoveNextAsync(); } public UniTask DisposeAsync() { return enumerator.DisposeAsync(); } } private readonly IUniTaskAsyncEnumerable<T> enumerable; private readonly CancellationToken cancellationToken; internal UniTaskCancelableAsyncEnumerable(IUniTaskAsyncEnumerable<T> enumerable, CancellationToken cancellationToken) { this.enumerable = enumerable; this.cancellationToken = cancellationToken; } public Enumerator GetAsyncEnumerator() { return new Enumerator(enumerable.GetAsyncEnumerator(cancellationToken)); } } public enum UniTaskStatus { Pending, Succeeded, Faulted, Canceled } public interface IUniTaskSource { UniTaskStatus GetStatus(short token); void OnCompleted(Action<object> continuation, object state, short token); void GetResult(short token); UniTaskStatus UnsafeGetStatus(); } public interface IUniTaskSource<out T> : IUniTaskSource { new T GetResult(short token); } public static class UniTaskStatusExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsCompleted(this UniTaskStatus status) { return status != UniTaskStatus.Pending; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsCompletedSuccessfully(this UniTaskStatus status) { return status == UniTaskStatus.Succeeded; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsCanceled(this UniTaskStatus status) { return status == UniTaskStatus.Canceled; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsFaulted(this UniTaskStatus status) { return status == UniTaskStatus.Faulted; } } public static class TaskTracker { public static class EditorEnableState { private static bool enableAutoReload; private static bool enableTracking; private static bool enableStackTrace; public static bool EnableAutoReload { get { return enableAutoReload; } set { enableAutoReload = value; EditorPrefs.SetBool("UniTaskTrackerWindow_EnableAutoReloadKey", value); } } public static bool EnableTracking { get { return enableTracking; } set { enableTracking = value; EditorPrefs.SetBool("UniTaskTrackerWindow_EnableTrackingKey", value); } } public static bool EnableStackTrace { get { return enableStackTrace; } set { enableStackTrace = value; EditorPrefs.SetBool("UniTaskTrackerWindow_EnableStackTraceKey", value); } } } private static int trackingId = 0; public const string EnableAutoReloadKey = "UniTaskTrackerWindow_EnableAutoReloadKey"; public const string EnableTrackingKey = "UniTaskTrackerWindow_EnableTrackingKey"; public const string EnableStackTraceKey = "UniTaskTrackerWindow_EnableStackTraceKey"; private static List<KeyValuePair<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>> listPool = new List<KeyValuePair<IUniTaskSource, (string, int, DateTime, string)>>(); private static readonly WeakDictionary<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)> tracking = new WeakDictionary<IUniTaskSource, (string, int, DateTime, string)>(); private static bool dirty; [Conditional("UNITY_EDITOR")] public static void TrackActiveTask(IUniTaskSource task, int skipFrame) { dirty = true; if (EditorEnableState.EnableTracking) { string item = (EditorEnableState.EnableStackTrace ? new StackTrace(skipFrame, fNeedFileInfo: true).CleanupAsyncStackTrace() : ""); string item2; if (EditorEnableState.EnableStackTrace) { StringBuilder stringBuilder = new StringBuilder(); TypeBeautify(task.GetType(), stringBuilder); item2 = stringBuilder.ToString(); } else { item2 = task.GetType().Name; } tracking.TryAdd(task, (item2, Interlocked.Increment(ref trackingId), DateTime.UtcNow, item)); } } [Conditional("UNITY_EDITOR")] public static void RemoveTracking(IUniTaskSource task) { dirty = true; if (EditorEnableState.EnableTracking) { tracking.TryRemove(task); } } public static bool CheckAndResetDirty() { bool result = dirty; dirty = false; return result; } public static void ForEachActiveTask(Action<int, string, UniTaskStatus, DateTime, string> action) { lock (listPool) { int num = tracking.ToList(ref listPool, clear: false); try { for (int i = 0; i < num; i++) { action(listPool[i].Value.trackingId, listPool[i].Value.formattedType, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace); listPool[i] = default(KeyValuePair<IUniTaskSource, (string, int, DateTime, string)>); } } catch { listPool.Clear(); throw; } } } private static void TypeBeautify(Type type, StringBuilder sb) { if (type.IsNested) { sb.Append(type.DeclaringType.Name.ToString()); sb.Append("."); } if (type.IsGenericType) { int num = type.Name.IndexOf("`"); if (num != -1) { sb.Append(type.Name.Substring(0, num)); } else { sb.Append(type.Name); } sb.Append("<"); bool flag = true; Type[] genericArguments = type.GetGenericArguments(); foreach (Type type2 in genericArguments) { if (!flag) { sb.Append(", "); } flag = false; TypeBeautify(type2, sb); } sb.Append(">"); } else { sb.Append(type.Name); } } } public abstract class MoveNextSource : IUniTaskSource<bool>, IUniTaskSource { protected UniTaskCompletionSourceCore<bool> completionSource; public bool GetResult(short token) { return completionSource.GetResult(token); } public UniTaskStatus GetStatus(short token) { return completionSource.GetStatus(token); } public void OnCompleted(Action<object> continuation, object state, short token) { completionSource.OnCompleted(continuation, state, token); } public UniTaskStatus UnsafeGetStatus() { return completionSource.UnsafeGetStatus(); } void IUniTaskSource.GetResult(short token) { completionSource.GetResult(token); } protected bool TryGetResult<T>(UniTask<T>.Awaiter awaiter, out T result) { try { result = awaiter.GetResult(); return true; } catch (Exception error) { completionSource.TrySetException(error); result = default(T); return false; } } protected bool TryGetResult(UniTask.Awaiter awaiter) { try { awaiter.GetResult(); return true; } catch (Exception error) { completionSource.TrySetException(error); return false; } } } public static class UniTaskLoopRunners { [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerInitialization { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerEarlyUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerFixedUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerPreUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerPreLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerPostLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastInitialization { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastEarlyUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastFixedUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastPreUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastPreLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastPostLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldInitialization { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldEarlyUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldFixedUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldPreUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldPreLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldPostLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldInitialization { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldEarlyUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldFixedUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldPreUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldPreLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldPostLateUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerTimeUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastTimeUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerYieldTimeUpdate { } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct UniTaskLoopRunnerLastYieldTimeUpdate { } } public enum PlayerLoopTiming { Initialization, LastInitialization, EarlyUpdate, LastEarlyUpdate, FixedUpdate, LastFixedUpdate, PreUpdate, LastPreUpdate, Update, LastUpdate, PreLateUpdate, LastPreLateUpdate, PostLateUpdate, LastPostLateUpdate, TimeUpdate, LastTimeUpdate } [Flags] public enum InjectPlayerLoopTimings { All = 0xFFFF, Standard = 0x7555, Minimum = 0x2110, Initialization = 1, LastInitialization = 2, EarlyUpdate = 4, LastEarlyUpdate = 8, FixedUpdate = 0x10, LastFixedUpdate = 0x20, PreUpdate = 0x40, LastPreUpdate = 0x80, Update = 0x100, LastUpdate = 0x200, PreLateUpdate = 0x400, LastPreLateUpdate = 0x800, PostLateUpdate = 0x1000, LastPostLateUpdate = 0x2000, TimeUpdate = 0x4000, LastTimeUpdate = 0x8000 } public interface IPlayerLoopItem { bool MoveNext(); } public static class PlayerLoopHelper { private static readonly ContinuationQueue ThrowMarkerContinuationQueue = new ContinuationQueue(PlayerLoopTiming.Initialization); private static readonly PlayerLoopRunner ThrowMarkerPlayerLoopRunner = new PlayerLoopRunner(PlayerLoopTiming.Initialization); private static int mainThreadId; private static string applicationDataPath; private static SynchronizationContext unitySynchronizationContext; private static ContinuationQueue[] yielders; private static PlayerLoopRunner[] runners; public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContext; public static int MainThreadId => mainThreadId; internal static string ApplicationDataPath => applicationDataPath; public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == mainThreadId; internal static bool IsEditorApplicationQuitting { get; private set; } private static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem, bool injectOnFirst, Type loopRunnerYieldType, ContinuationQueue cq, Type loopRunnerType, PlayerLoopRunner runner) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) EditorApplication.playModeStateChanged += delegate(PlayModeStateChange state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 if ((int)state == 0 || (int)state == 1) { IsEditorApplicationQuitting = true; if (runner != null) { runner.Run(); runner.Clear(); } if (cq != null) { cq.Run(); cq.Clear(); } IsEditorApplicationQuitting = false; } }; PlayerLoopSystem val = default(PlayerLoopSystem); val.type = loopRunnerYieldType; val.updateDelegate = new UpdateFunction(cq.Run); PlayerLoopSystem val2 = val; val = default(PlayerLoopSystem); val.type = loopRunnerType; val.updateDelegate = new UpdateFunction(runner.Run); PlayerLoopSystem val3 = val; PlayerLoopSystem[] array = RemoveRunner(loopSystem, loopRunnerYieldType, loopRunnerType); PlayerLoopSystem[] array2 = (PlayerLoopSystem[])(object)new PlayerLoopSystem[array.Length + 2]; Array.Copy(array, 0, array2, injectOnFirst ? 2 : 0, array.Length); if (injectOnFirst) { array2[0] = val2; array2[1] = val3; } else { array2[^2] = val2; array2[^1] = val3; } return array2; } private static PlayerLoopSystem[] RemoveRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType, Type loopRunnerType) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return loopSystem.subSystemList.Where((PlayerLoopSystem ls) => ls.type != loopRunnerYieldType && ls.type != loopRunnerType).ToArray(); } private static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) PlayerLoopSystem val = default(PlayerLoopSystem); val.type = typeof(UniTaskSynchronizationContext); val.updateDelegate = new UpdateFunction(UniTaskSynchronizationContext.Run); PlayerLoopSystem item = val; List<PlayerLoopSystem> list = new List<PlayerLoopSystem>(loopSystem.subSystemList.Where((PlayerLoopSystem ls) => ls.type != typeof(UniTaskSynchronizationContext)).ToArray()); int num = list.FindIndex((PlayerLoopSystem x) => x.type.Name == "ScriptRunDelayedTasks"); if (num == -1) { num = list.FindIndex((PlayerLoopSystem x) => x.type.Name == "UniTaskLoopRunnerUpdate"); } list.Insert(num + 1, item); return list.ToArray(); } [RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)] private static void Init() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) unitySynchronizationContext = SynchronizationContext.Current; mainThreadId = Thread.CurrentThread.ManagedThreadId; try { applicationDataPath = Application.dataPath; } catch { } if ((EditorSettings.enterPlayModeOptionsEnabled && ((Enum)EditorSettings.enterPlayModeOptions).HasFlag((Enum)(object)(EnterPlayModeOptions)1)) || runners == null) { PlayerLoopSystem playerLoop = PlayerLoop.GetCurrentPlayerLoop(); Initialize(ref playerLoop); } } [InitializeOnLoadMethod] private static void InitOnEditor() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Init(); EditorApplication.update = (CallbackFunction)Delegate.Combine((Delegate?)(object)EditorApplication.update, (Delegate?)new CallbackFunction(ForceEditorPlayerLoopUpdate)); } private static void ForceEditorPlayerLoopUpdate() { if (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isCompiling || EditorApplication.isUpdating) { return; } if (yielders != null) { ContinuationQueue[] array = yielders; for (int i = 0; i < array.Length; i++) { array[i]?.Run(); } } if (runners != null) { PlayerLoopRunner[] array2 = runners; for (int i = 0; i < array2.Length; i++) { array2[i]?.Run(); } } UniTaskSynchronizationContext.Run(); } private static int FindLoopSystemIndex(PlayerLoopSystem[] playerLoopList, Type systemType) { for (int i = 0; i < playerLoopList.Length; i++) { if (playerLoopList[i].type == systemType) { return i; } } throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName); } private static void InsertLoop(PlayerLoopSystem[] copyList, InjectPlayerLoopTimings injectTimings, Type loopType, InjectPlayerLoopTimings targetTimings, int index, bool injectOnFirst, Type loopRunnerYieldType, Type loopRunnerType, PlayerLoopTiming playerLoopTiming) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) int num = FindLoopSystemIndex(copyList, loopType); if ((injectTimings & targetTimings) == targetTimings) { copyList[num].subSystemList = InsertRunner(copyList[num], injectOnFirst, loopRunnerYieldType, yielders[index] = new ContinuationQueue(playerLoopTiming), loopRunnerType, runners[index] = new PlayerLoopRunner(playerLoopTiming)); } else { copyList[num].subSystemList = RemoveRunner(copyList[num], loopRunnerYieldType, loopRunnerType); } } public static void Initialize(ref PlayerLoopSystem playerLoop, InjectPlayerLoopTimings injectTimings = InjectPlayerLoopTimings.All) { //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) yielders = new ContinuationQueue[16]; runners = new PlayerLoopRunner[16]; PlayerLoopSystem[] array = playerLoop.subSystemList.ToArray(); InsertLoop(array, injectTimings, typeof(Initialization), InjectPlayerLoopTimings.Initialization, 0, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), PlayerLoopTiming.Initialization); InsertLoop(array, injectTimings, typeof(Initialization), InjectPlayerLoopTimings.LastInitialization, 1, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), PlayerLoopTiming.LastInitialization); InsertLoop(array, injectTimings, typeof(EarlyUpdate), InjectPlayerLoopTimings.EarlyUpdate, 2, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), PlayerLoopTiming.EarlyUpdate); InsertLoop(array, injectTimings, typeof(EarlyUpdate), InjectPlayerLoopTimings.LastEarlyUpdate, 3, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), PlayerLoopTiming.LastEarlyUpdate); InsertLoop(array, injectTimings, typeof(FixedUpdate), InjectPlayerLoopTimings.FixedUpdate, 4, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), PlayerLoopTiming.FixedUpdate); InsertLoop(array, injectTimings, typeof(FixedUpdate), InjectPlayerLoopTimings.LastFixedUpdate, 5, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), PlayerLoopTiming.LastFixedUpdate); InsertLoop(array, injectTimings, typeof(PreUpdate), InjectPlayerLoopTimings.PreUpdate, 6, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), PlayerLoopTiming.PreUpdate); InsertLoop(array, injectTimings, typeof(PreUpdate), InjectPlayerLoopTimings.LastPreUpdate, 7, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), PlayerLoopTiming.LastPreUpdate); InsertLoop(array, injectTimings, typeof(Update), InjectPlayerLoopTimings.Update, 8, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), PlayerLoopTiming.Update); InsertLoop(array, injectTimings, typeof(Update), InjectPlayerLoopTimings.LastUpdate, 9, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), PlayerLoopTiming.LastUpdate); InsertLoop(array, injectTimings, typeof(PreLateUpdate), InjectPlayerLoopTimings.PreLateUpdate, 10, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), PlayerLoopTiming.PreLateUpdate); InsertLoop(array, injectTimings, typeof(PreLateUpdate), InjectPlayerLoopTimings.LastPreLateUpdate, 11, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), PlayerLoopTiming.LastPreLateUpdate); InsertLoop(array, injectTimings, typeof(PostLateUpdate), InjectPlayerLoopTimings.PostLateUpdate, 12, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), PlayerLoopTiming.PostLateUpdate); InsertLoop(array, injectTimings, typeof(PostLateUpdate), InjectPlayerLoopTimings.LastPostLateUpdate, 13, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), PlayerLoopTiming.LastPostLateUpdate); InsertLoop(array, injectTimings, typeof(TimeUpdate), InjectPlayerLoopTimings.TimeUpdate, 14, injectOnFirst: true, typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerTimeUpdate), PlayerLoopTiming.TimeUpdate); InsertLoop(array, injectTimings, typeof(TimeUpdate), InjectPlayerLoopTimings.LastTimeUpdate, 15, injectOnFirst: false, typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastTimeUpdate), PlayerLoopTiming.LastTimeUpdate); int num = FindLoopSystemIndex(array, typeof(Update)); array[num].subSystemList = InsertUniTaskSynchronizationContext(array[num]); playerLoop.subSystemList = array; PlayerLoop.SetPlayerLoop(playerLoop); } public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action) { PlayerLoopRunner obj = runners[(int)timing]; if (obj == null) { ThrowInvalidLoopTiming(timing); } obj.AddAction(action); } private static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming) { throw new InvalidOperationException("Target playerLoopTiming is not injected. Please check PlayerLoopHelper.Initialize. PlayerLoopTiming:" + playerLoopTiming); } public static void AddContinuation(PlayerLoopTiming timing, Action continuation) { ContinuationQueue obj = yielders[(int)timing]; if (obj == null) { ThrowInvalidLoopTiming(timing); } obj.Enqueue(continuation); } public static void DumpCurrentPlayerLoop() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) PlayerLoopSystem currentPlayerLoop = PlayerLoop.GetCurrentPlayerLoop(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("PlayerLoop List"); PlayerLoopSystem[] subSystemList = currentPlayerLoop.subSystemList; for (int i = 0; i < subSystemList.Length; i++) { PlayerLoopSystem val = subSystemList[i]; stringBuilder.AppendFormat("------{0}------", val.type.Name); stringBuilder.AppendLine(); if (val.subSystemList == null) { stringBuilder.AppendFormat("{0} has no subsystems!", ((object)(PlayerLoopSystem)(ref val)).ToString()); stringBuilder.AppendLine(); continue; } PlayerLoopSystem[] subSystemList2 = val.subSystemList; foreach (PlayerLoopSystem val2 in subSystemList2) { stringBuilder.AppendFormat("{0}", val2.type.Name); stringBuilder.AppendLine(); if (val2.subSystemList != null) { Debug.LogWarning((object)("More Subsystem:" + val2.subSystemList.Length)); } } } Debug.Log((object)stringBuilder.ToString()); } public static bool IsInjectedUniTaskPlayerLoop() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) PlayerLoopSystem[] subSystemList = PlayerLoop.GetCurrentPlayerLoop().subSystemList; foreach (PlayerLoopSystem val in subSystemList) { if (val.subSystemList == null) { continue; } PlayerLoopSystem[] subSystemList2 = val.subSystemList; for (int j = 0; j < subSystemList2.Length; j++) { if (subSystemList2[j].type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization)) { return true; } } } return false; } } public abstract class PlayerLoopTimer : IDisposable, IPlayerLoopItem { private readonly CancellationToken cancellationToken; private readonly Action<object> timerCallback; private readonly object state; private readonly PlayerLoopTiming playerLoopTiming; private readonly bool periodic; private bool isRunning; private bool tryStop; private bool isDisposed; protected PlayerLoopTimer(bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state) { this.periodic = periodic; this.playerLoopTiming = playerLoopTiming; this.cancellationToken = cancellationToken; this.timerCallback = timerCallback; this.state = state; } public static PlayerLoopTimer Create(TimeSpan interval, bool periodic, DelayType delayType, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state) { if (PlayerLoopHelper.IsMainThread && !EditorApplication.isPlaying) { delayType = DelayType.Realtime; } return delayType switch { DelayType.UnscaledDeltaTime => new IgnoreTimeScalePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state), DelayType.Realtime => new RealtimePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state), _ => new DeltaTimePlayerLoopTimer(interval, periodic, playerLoopTiming, cancellationToken, timerCallback, state), }; } public static PlayerLoopTimer StartNew(TimeSpan interval, bool periodic, DelayType delayType, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state) { PlayerLoopTimer playerLoopTimer = Create(interval, periodic, delayType, playerLoopTiming, cancellationToken, timerCallback, state); playerLoopTimer.Restart(); return playerLoopTimer; } public void Restart() { if (isDisposed) { throw new ObjectDisposedException(null); } ResetCore(null); if (!isRunning) { isRunning = true; PlayerLoopHelper.AddAction(playerLoopTiming, this); } tryStop = false; } public void Restart(TimeSpan interval) { if (isDisposed) { throw new ObjectDisposedException(null); } ResetCore(interval); if (!isRunning) { isRunning = true; PlayerLoopHelper.AddAction(playerLoopTiming, this); } tryStop = false; } public void Stop() { tryStop = true; } protected abstract void ResetCore(TimeSpan? newInterval); public void Dispose() { isDisposed = true; } bool IPlayerLoopItem.MoveNext() { if (isDisposed) { isRunning = false; return false; } if (tryStop) { isRunning = false; return false; } CancellationToken cancellationToken = this.cancellationToken; if (cancellationToken.IsCancellationRequested) { isRunning = false; return false; } if (!MoveNextCore()) { timerCallback(state); if (periodic) { ResetCore(null); return true; } isRunning = false; return false; } return true; } protected abstract bool MoveNextCore(); } internal sealed class DeltaTimePlayerLoopTimer : PlayerLoopTimer { private int initialFrame; private float elapsed; private float interval; public DeltaTimePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state) : base(periodic, playerLoopTiming, cancellationToken, timerCallback, state) { ResetCore(interval); } protected override bool MoveNextCore() { if (elapsed == 0f && initialFrame == Time.frameCount) { return true; } elapsed += Time.deltaTime; if (elapsed >= interval) { return false; } return true; } protected override void ResetCore(TimeSpan? interval) { elapsed = 0f; initialFrame = (PlayerLoopHelper.IsMainThread ? Time.frameCount : (-1)); if (interval.HasValue) { this.interval = (float)interval.Value.TotalSeconds; } } } internal sealed class IgnoreTimeScalePlayerLoopTimer : PlayerLoopTimer { private int initialFrame; private float elapsed; private float interval; public IgnoreTimeScalePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state) : base(periodic, playerLoopTiming, cancellationToken, timerCallback, state) { ResetCore(interval); } protected override bool MoveNextCore() { if (elapsed == 0f && initialFrame == Time.frameCount) { return true; } elapsed += Time.unscaledDeltaTime; if (elapsed >= interval) { return false; } return true; } protected override void ResetCore(TimeSpan? interval) { elapsed = 0f; initialFrame = (PlayerLoopHelper.IsMainThread ? Time.frameCount : (-1)); if (interval.HasValue) { this.interval = (float)interval.Value.TotalSeconds; } } } internal sealed class RealtimePlayerLoopTimer : PlayerLoopTimer { private ValueStopwatch stopwatch; private long intervalTicks; public RealtimePlayerLoopTimer(TimeSpan interval, bool periodic, PlayerLoopTiming playerLoopTiming, CancellationToken cancellationToken, Action<object> timerCallback, object state) : base(periodic, playerLoopTiming, cancellationToken, timerCallback, state) { ResetCore(interval); } protected override bool MoveNextCore() { if (stopwatch.ElapsedTicks >= intervalTicks) { return false; } return true; } protected override void ResetCore(TimeSpan? interval) { stopwatch = ValueStopwatch.StartNew(); if (interval.HasValue) { intervalTicks = interval.Value.Ticks; } } } public static class Progress { private sealed class NullProgress<T> : IProgress<T> { public static readonly IProgress<T> Instance = new NullProgress<T>(); private NullProgress() { } public void Report(T value) { } } private sealed class AnonymousProgress<T> : IProgress<T> { private readonly Action<T> action; public AnonymousProgress(Action<T> action) { this.action = action; } public void Report(T value) { action(value); } } private sealed class OnlyValueChangedProgress<T> : IProgress<T> { private readonly Action<T> action; private readonly IEqualityComparer<T> comparer; private bool isFirstCall; private T latestValue; public OnlyValueChangedProgress(Action<T> action, IEqualityComparer<T> comparer) { this.action = action; this.comparer = comparer; isFirstCall = true; } public void Report(T value) { if (isFirstCall) { isFirstCall = false; } else if (comparer.Equals(value, latestValue)) { return; } latestValue = value; action(value); } } public static IProgress<T> Create<T>(Action<T> handler) { if (handler == null) { return NullProgress<T>.Instance; } return new AnonymousProgress<T>(handler); } public static IProgress<T> CreateOnlyValueChanged<T>(Action<T> handler, IEqualityComparer<T> comparer = null) { if (handler == null) { return NullProgress<T>.Instance; } return new OnlyValueChangedProgress<T>(handler, comparer ?? UnityEqualityComparer.GetDefault<T>()); } } public static class TaskPool { internal static int MaxPoolSize; private static Dictionary<Type, Func<int>> sizes; static TaskPool() { sizes = new Dictionary<Type, Func<int>>(); try { string environmentVariable = Environment.GetEnvironmentVariable("UNITASK_MAX_POOLSIZE"); if (environmentVariable != null && int.TryParse(environmentVariable, out var result)) { MaxPoolSize = result; return; } } catch { } MaxPoolSize = int.MaxValue; } public static void SetMaxPoolSize(int maxPoolSize) { MaxPoolSize = maxPoolSize; } public static IEnumerable<(Type, int)> GetCacheSizeInfo() { lock (sizes) { foreach (KeyValuePair<Type, Func<int>> size in sizes) { yield return (size.Key, size.Value()); } } } public static void RegisterSizeGetter(Type type, Func<int> getSize) { lock (sizes) { sizes[type] = getSize; } } } public interface ITaskPoolNode<T> { ref T NextNode { get; } } [StructLayout(LayoutKind.Auto)] public struct TaskPool<T> where T : class, ITaskPoolNode<T> { private int gate; private int size; private T root; public int Size => size; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryPop(out T result) { if (Interlocked.CompareExchange(ref gate, 1, 0) == 0) { T val = root; if (val != null) { ref T nextNode = ref val.NextNode; root = nextNode; nextNode = null; size--; result = val; Volatile.Write(ref gate, 0); return true; } Volatile.Write(ref gate, 0); } result = null; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryPush(T item) { if (Interlocked.CompareExchange(ref gate, 1, 0) == 0) { if (size < TaskPool.MaxPoolSize) { item.NextNode = root; root = item; size++; Volatile.Write(ref gate, 0); return true; } Volatile.Write(ref gate, 0); } return false; } } public sealed class TimeoutController : IDisposable { private static readonly Action<object> CancelCancellationTokenSourceStateDelegate = CancelCancellationTokenSourceState; private CancellationTokenSource timeoutSource; private CancellationTokenSource linkedSource; private PlayerLoopTimer timer; private bool isDisposed; private readonly DelayType delayType; private readonly PlayerLoopTiming delayTiming; private readonly CancellationTokenSource originalLinkCancellationTokenSource; private static void CancelCancellationTokenSourceState(object state) { ((CancellationTokenSource)state).Cancel(); } public TimeoutController(DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update) { timeoutSource = new CancellationTokenSource(); originalLinkCancellationTokenSource = null; linkedSource = null; this.delayType = delayType; this.delayTiming = delayTiming; } public TimeoutController(CancellationTokenSource linkCancellationTokenSource, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update) { timeoutSource = new CancellationTokenSource(); originalLinkCancellationTokenSource = linkCancellationTokenSource; linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, linkCancellationTokenSource.Token); this.delayType = delayType; this.delayTiming = delayTiming; } public CancellationToken Timeout(int millisecondsTimeout) { return Timeout(TimeSpan.FromMilliseconds(millisecondsTimeout)); } public CancellationToken Timeout(TimeSpan timeout) { if (originalLinkCancellationTokenSource != null && originalLinkCancellationTokenSource.IsCancellationRequested) { return originalLinkCancellationTokenSource.Token; } if (timeoutSource.IsCancellationRequested) { timeoutSource.Dispose(); timeoutSource = new CancellationTokenSource(); if (linkedSource != null) { linkedSource.Cancel(); linkedSource.Dispose(); linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, originalLinkCancellationTokenSource.Token); } timer?.Dispose(); timer = null; } CancellationToken token = ((linkedSource != null) ? linkedSource : timeoutSource).Token; if (timer == null) { timer = PlayerLoopTimer.StartNew(timeout, periodic: false, delayType, delayTiming, token, CancelCancellationTokenSourceStateDelegate, timeoutSource); } else { timer.Restart(timeout); } return token; } public bool IsTimeout() { return timeoutSource.IsCancellationRequested; } public void Reset() { timer?.Stop(); } public void Dispose() { if (isDisposed) { return; } try { timer?.Dispose(); timeoutSource.Cancel(); timeoutSource.Dispose(); if (linkedSource != null) { linkedSource.Cancel(); linkedSource.Dispose(); } } finally { isDisposed = true; } } } public interface ITriggerHandler<T> { ITriggerHandler<T> Prev { get; set; } ITriggerHandler<T> Next { get; set; } void OnNext(T value); void OnError(Exception ex); void OnCompleted(); void OnCanceled(CancellationToken cancellationToken); } public struct TriggerEvent<T> { private ITriggerHandler<T> head; private ITriggerHandler<T> iteratingHead; private bool preserveRemoveSelf; private ITriggerHandler<T> iteratingNode; private void LogError(Exception ex) { Debug.LogException(ex); } public void SetResult(T value) { if (iteratingNode != null) { throw new InvalidOperationException("Can not trigger itself in iterating."); } ITriggerHandler<T> triggerHandler = head; while (triggerHandler != null) { iteratingNode = triggerHandler; try { triggerHandler.OnNext(value); } catch (Exception ex) { LogError(ex); Remove(triggerHandler); } if (preserveRemoveSelf) { preserveRemoveSelf = false; iteratingNode = null; ITriggerHandler<T> next = triggerHandler.Next; Remove(triggerHandler); triggerHandler = next; } else { triggerHandler = triggerHandler.Next; } } iteratingNode = null; if (iteratingHead != null) { Add(iteratingHead); iteratingHead = null; } } public void SetCanceled(CancellationToken cancellationToken) { if (iteratingNode != null) { throw new InvalidOperationException("Can not trigger itself in iterating."); } ITriggerHandler<T> triggerHandler = head; while (triggerHandler != null) { iteratingNode = triggerHandler; try { triggerHandler.OnCanceled(cancellationToken); } catch (Exception ex) { LogError(ex); } preserveRemoveSelf = false; iteratingNode = null; ITriggerHandler<T> next = triggerHandler.Next; Remove(triggerHandler); triggerHandler = next; } iteratingNode = null; if (iteratingHead != null) { Add(iteratingHead); iteratingHead = null; } } public void SetCompleted() { if (iteratingNode != null) { throw new InvalidOperationException("Can not trigger itself in iterating."); } ITriggerHandler<T> triggerHandler = head; while (triggerHandler != null) { iteratingNode = triggerHandler; try { triggerHandler.OnCompleted(); } catch (Exception ex) { LogError(ex); } preserveRemoveSelf = false; iteratingNode = null; ITriggerHandler<T> next = triggerHandler.Next; Remove(triggerHandler); triggerHandler = next; } iteratingNode = null; if (iteratingHead != null) { Add(iteratingHead); iteratingHead = null; } } public void SetError(Exception exception) { if (iteratingNode != null) { throw new InvalidOperationException("Can not trigger itself in iterating."); } ITriggerHandler<T> triggerHandler = head; while (triggerHandler != null) { iteratingNode = triggerHandler; try { triggerHandler.OnError(exception); } catch (Exception ex) { LogError(ex); } preserveRemoveSelf = false; iteratingNode = null; ITriggerHandler<T> next = triggerHandler.Next; Remove(triggerHandler); triggerHandler = next; } iteratingNode = null; if (iteratingHead != null) { Add(iteratingHead); iteratingHead = null; } } public void Add(ITriggerHandler<T> handler) { if (handler == null) { throw new ArgumentNullException("handler"); } if (head == null) { head = handler; } else if (iteratingNode != null) { if (iteratingHead == null) { iteratingHead = handler; return; } ITriggerHandler<T> prev = iteratingHead.Prev; if (prev == null) { iteratingHead.Prev = handler; iteratingHead.Next = handler; handler.Prev = iteratingHead; } else { iteratingHead.Prev = handler; prev.Next = handler; handler.Prev = prev; } } else { ITriggerHandler<T> prev2 = head.Prev; if (prev2 == null) { head.Prev = handler; head.Next = handler; handler.Prev = head; } else { head.Prev = handler; prev2.Next = handler; handler.Prev = prev2; } } } public void Remove(ITriggerHandler<T> handler) { if (handler == null) { throw new ArgumentNullException("handler"); } if (iteratingNode != null && iteratingNode == handler) { preserveRemoveSelf = true; return; } ITriggerHandler<T> prev = handler.Prev; ITriggerHandler<T> next = handler.Next; if (next != null) { next.Prev = prev; } if (handler == head) { head = next; } else if (handler == iteratingHead) { iteratingHead = next; } else if (prev != null) { prev.Next = next; } if (head != null && head.Prev == handler) { if (prev != head) { head.Prev = prev; } else { head.Prev = null; } } if (iteratingHead != null && iteratingHead.Prev == handler) { if (prev != iteratingHead.Prev) { iteratingHead.Prev = prev; } else { iteratingHead.Prev = null; } } handler.Prev = null; handler.Next = null; } } public static class UniTaskCancellationExtensions { public static CancellationToken GetCancellationTokenOnDestroy(this GameObject gameObject) { return gameObject.GetAsyncDestroyTrigger().CancellationToken; } public static CancellationToken GetCancellationTokenOnDestroy(this Component component) { return component.GetAsyncDestroyTrigger().CancellationToken; } } [StructLayout(LayoutKind.Auto)] [AsyncMethodBuilder(typeof(AsyncUniTaskMethodBuilder))] public readonly struct UniTask { private sealed class YieldPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<YieldPromise> { private static TaskPool<YieldPromise> pool; private YieldPromise nextNode; private CancellationToken cancellationToken; private UniTaskCompletionSourceCore<object> core; public ref YieldPromise NextNode => ref nextNode; static YieldPromise() { TaskPool.RegisterSizeGetter(typeof(YieldPromise), () => pool.Size); } private YieldPromise() { } public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token) { if (cancellationToken.IsCancellationRequested) { return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } if (!pool.TryPop(out var result)) { result = new YieldPromise(); } result.cancellationToken = cancellationToken; TaskTracker.TrackActiveTask(result, 3); PlayerLoopHelper.AddAction(timing, result); token = result.core.Version; return result; } public void GetResult(short token) { try { core.GetResult(token); } finally { TryReturn(); } } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } public void OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public bool MoveNext() { if (cancellationToken.IsCancellationRequested) { core.TrySetCanceled(cancellationToken); return false; } core.TrySetResult(null); return false; } private bool TryReturn() { TaskTracker.RemoveTracking(this); core.Reset(); cancellationToken = default(CancellationToken); return pool.TryPush(this); } } private sealed class NextFramePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<NextFramePromise> { private static TaskPool<NextFramePromise> pool; private NextFramePromise nextNode; private int frameCount; private CancellationToken cancellationToken; private UniTaskCompletionSourceCore<AsyncUnit> core; public ref NextFramePromise NextNode => ref nextNode; static NextFramePromise() { TaskPool.RegisterSizeGetter(typeof(NextFramePromise), () => pool.Size); } private NextFramePromise() { } public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token) { if (cancellationToken.IsCancellationRequested) { return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token); } if (!pool.TryPop(out var result)) { result = new NextFramePromise(); } result.frameCount = (PlayerLoopHelper.IsMainThread ? Time.frameCount : (-1)); result.cancellationToken = cancellationToken; TaskTracker.TrackActiveTask(result, 3); PlayerLoopHelper.AddAction(timing, result); token = result.core.Version; return result; } public void GetResult(short token) { try { core.GetResult(token); } finally { TryReturn(); } } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } public void OnCompleted(Action<object> continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public bool MoveNext() { if (cancellationToken.IsCancellationRequested) { core.TrySetCanceled(cancellationToken); return false; } if (frameCount == Time.frameCount) { return true; } core.TrySetResult(AsyncUnit.Default); return false; } private bool TryReturn() { TaskTracker.RemoveTracking(this); core.Reset(); cancellationToken = default(CancellationToken); return pool.TryPush(this); } } private sealed class WaitForEndOfFramePromise : IUniTaskSource, ITaskPoolNode<WaitForEndOfFramePromise>, IEnumerator { private static TaskPool<WaitForEndOfFramePromise> pool; private WaitForEndOfFramePromise nextNode; private CancellationToken cancellationToken; private UniTaskCompletionSourceCore<object> core; private static readonly WaitForEndOfFrame waitForEndOfFrameYieldInstruction; private bool isFirst = true; public ref WaitForEndOfFramePromise NextNode => ref nextNode; object IEnumerator.Current => waitForEndOfFrameYieldInstruction; st
plugins/OCDheim.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using OCDheim.Utilities; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("OCDheim")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OCDheim")] [assembly: AssemblyCopyright("Copyright \ufffd 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.0.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.2.0")] [module: UnverifiableCode] namespace OCDheim { public class GroundLevelSpinner { public static readonly GroundLevelSpinner RaiseGroundSpinner = new GroundLevelSpinner(1f, 0f, 1f); public static readonly GroundLevelSpinner LowerGroundSpinner = new GroundLevelSpinner(-0.5f, -1f, 0f); public float value { get; private set; } private float maxValue { get; } private float minValue { get; } private GroundLevelSpinner(float value, float minValue, float maxValue) { this.value = value; this.minValue = minValue; this.maxValue = maxValue; } public void Refresh() { float num = KeyBinder.ScrollΔ(); if (num > 0f) { Up(num); } if (num < 0f) { Down(num); } } private void Up(float scrollΔ) { if (value + scrollΔ > maxValue) { value = maxValue; } else { value = Mathf.Round((value + scrollΔ) * 100f) / 100f; } } private void Down(float scrollΔ) { if (value + scrollΔ < minValue) { value = minValue; } else { value = Mathf.Round((value + scrollΔ) * 100f) / 100f; } } } [HarmonyPatch] public static class BlockCameraZoom { [HarmonyPrefix] [HarmonyPatch(typeof(ZInput))] [HarmonyPatch("GetMouseScrollWheel")] public static bool Prefix(ref float __result) { if (PlayerHelpers.player.HasRaiseGroundTerraformToolEquipped()) { __result = 0f; return false; } return true; } } [HarmonyPatch] public class KeyBinder : MonoBehaviour { private static readonly ButtonConfig SnapModeKey = new ButtonConfig { Name = "SnapModeKey", Key = (KeyCode)304 }; private static readonly ButtonConfig SnapModeJoy = new ButtonConfig { Name = "SnapModeJoy", GamepadButton = (GamepadButton)10 }; private static readonly ButtonConfig GridModeKey = new ButtonConfig { Name = "GridModeKey", Key = (KeyCode)308 }; private static readonly ButtonConfig GridModeJoy = new ButtonConfig { Name = "GridModeJoy", GamepadButton = (GamepadButton)16 }; private static readonly ButtonConfig PrecisionModeKey = new ButtonConfig { Name = "PrecisionModeKey", Key = (KeyCode)122 }; private static readonly ButtonConfig PrecisionModeJoy = new ButtonConfig { Name = "PrecisionModeJoy", GamepadButton = (GamepadButton)7 }; private const string MouseScrollWheel = "Mouse ScrollWheel"; private const string JoyScrollUnlock = "JoyLTrigger"; private const string JoyScrollDown = "JoyDPadDown"; private const string JoyScrollUp = "JoyDPadUp"; private const float ScrollPrecision = 0.01f; private static bool _gridModeEnabled; private static bool _gridModeFreshlyEnabled; private static bool _gridModeFreshlyDisabled; private static bool snapModeDisabled => ZInput.GetButton(SnapModeKey.Name) || ZInput.GetButton(SnapModeJoy.Name); public static bool snapModeEnabled => !snapModeDisabled; public static bool gridModeEnabled { get { return _gridModeEnabled; } private set { _gridModeEnabled = value; _gridModeFreshlyEnabled = value; _gridModeFreshlyDisabled = !value; } } public static bool gridModeDisabled => !gridModeEnabled; public static bool gridModFreshlyEnabled { get { bool gridModeFreshlyEnabled = _gridModeFreshlyEnabled; _gridModeFreshlyEnabled = false; return gridModeFreshlyEnabled; } } public static bool gridModFreshlyDisabled { get { bool gridModeFreshlyDisabled = _gridModeFreshlyDisabled; _gridModeFreshlyDisabled = false; return gridModeFreshlyDisabled; } } public static PrecisionMode precisionMode { get; private set; } = PrecisionMode.ORDINARY; private void Awake() { InputManager.Instance.AddButton("dymek.dev.OCDheim", SnapModeJoy); InputManager.Instance.AddButton("dymek.dev.OCDheim", SnapModeKey); InputManager.Instance.AddButton("dymek.dev.OCDheim", GridModeKey); InputManager.Instance.AddButton("dymek.dev.OCDheim", GridModeJoy); InputManager.Instance.AddButton("dymek.dev.OCDheim", PrecisionModeKey); InputManager.Instance.AddButton("dymek.dev.OCDheim", PrecisionModeJoy); } private void Update() { bool flag = ((ZInput.GetButtonDown(GridModeKey.Name) || (snapModeEnabled && ZInput.GetButtonDown(GridModeJoy.Name))) && (gridModeEnabled || PlayerHelpers.player.HasConstructionToolEquipped())) || (gridModeEnabled && !PlayerHelpers.player.HasConstructionToolEquipped()); bool flag2 = ((ZInput.GetButtonDown(PrecisionModeKey.Name) || (snapModeEnabled && ZInput.GetButtonDown(PrecisionModeJoy.Name))) && (precisionMode == PrecisionMode.SUPERIOR || PlayerHelpers.player.HasBuildPieceEquipped())) || (precisionMode == PrecisionMode.SUPERIOR && !PlayerHelpers.player.HasBuildPieceEquipped()); if (flag) { gridModeEnabled = !gridModeEnabled; Logger.Info(() => "[" + (gridModeEnabled ? "ENABLED" : "DISABLED") + "] GRID MODE"); } if (flag2) { precisionMode = ((precisionMode != PrecisionMode.ORDINARY) ? PrecisionMode.ORDINARY : PrecisionMode.SUPERIOR); Logger.Info(() => "[" + ((precisionMode == PrecisionMode.SUPERIOR) ? "ENABLED" : "DISABLED") + "] PRECISION MODE"); } } public static float ScrollΔ() { float axis = Input.GetAxis("Mouse ScrollWheel"); if (axis != 0f) { return (axis > 0f) ? 0.01f : (-0.01f); } if (ZInput.GetButton("JoyLTrigger") && ZInput.GetButtonDown("JoyDPadDown")) { return -0.01f; } if (ZInput.GetButton("JoyLTrigger") && ZInput.GetButtonDown("JoyDPadUp")) { return 0.01f; } return axis; } } [HarmonyPatch] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("dymek.dev.OCDheim", "OCDheim", "0.2.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class OCDheim : BaseUnityPlugin { public const string GUID = "dymek.dev.OCDheim"; private const string Name = "OCDheim"; private const string Version = "0.2.0"; public static AssetBundle resourceBundle { get; } = LoadResourceBundle(); private Texture2D brick1x1 { get; } = LoadTextureFromDisk("brick_1x1.png"); private Texture2D brick2x1 { get; } = LoadTextureFromDisk("brick_2x1.png"); private Texture2D brick1x2 { get; } = LoadTextureFromDisk("brick_1x2.png"); private Texture2D brick4x2 { get; } = LoadTextureFromDisk("brick_4x2.png"); private Harmony harmony { get; } = new Harmony("dymek.dev.OCDheim"); private static AssetBundle LoadResourceBundle() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 RuntimePlatform platform = Application.platform; RuntimePlatform val = platform; if ((int)val <= 2) { if ((int)val <= 1) { return AssetUtils.LoadAssetBundleFromResources(Path.Combine("bundle_osx")); } if ((int)val == 2) { goto IL_002d; } } else { if ((int)val == 7) { goto IL_002d; } if ((int)val == 13 || (int)val == 16) { return AssetUtils.LoadAssetBundleFromResources(Path.Combine("bundle_linux")); } } throw new PlatformNotSupportedException(); IL_002d: return AssetUtils.LoadAssetBundleFromResources(Path.Combine("bundle_windows")); } public static Texture2D LoadTextureFromDisk(string fileName) { string path = Path.GetDirectoryName(typeof(OCDheim).Assembly.Location) ?? throw new InvalidOperationException(); string text = Path.Combine(path, fileName); return AssetUtils.LoadTexture(text, true); } private void Awake() { harmony.PatchAll(); ((Component)this).gameObject.AddComponent<KeyBinder>(); PrefabManager.OnVanillaPrefabsAvailable += AddOCDheimToolPieces; PrefabManager.OnVanillaPrefabsAvailable += AddOCDheimBuildPieces; PrefabManager.OnVanillaPrefabsAvailable += ModVanillaValheimTools; } [HarmonyPostfix] [HarmonyPatch(typeof(Player))] [HarmonyPatch("OnSpawned")] private static void OnPlayerAvailable() { Refresher.Of(PrecisionDrill.groundLevels); Refresher.Of(PrecisionDrill.floorLevels); } private void AddOCDheimToolPieces() { AddToolPiece<RemoveModificationsOverlayVisualizer>("Remove Terrain Modifications", "mud_road_v2", "Hoe", OverlayVisualizer.remove); } private void AddToolPiece<TOverlayVisualizer>(string pieceName, string basePieceName, string pieceTable, Texture2D iconTexture, bool level = false, bool raise = false, bool smooth = false, bool paint = false) where TOverlayVisualizer : OverlayVisualizer { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown CustomPiece piece = PieceManager.Instance.GetPiece(pieceName); if (piece == null) { Sprite icon = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), Vector2.zero); CustomPiece val = new CustomPiece(pieceName, basePieceName, new PieceConfig { Name = pieceName, Icon = icon, PieceTable = pieceTable }); Settings settings = val.PiecePrefab.GetComponent<TerrainOp>().m_settings; settings.m_level = level; settings.m_raise = raise; settings.m_smooth = smooth; settings.m_paintCleared = paint; val.PiecePrefab.AddComponent<TOverlayVisualizer>(); PieceManager.Instance.AddPiece(val); } } private void AddOCDheimBuildPieces() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) AddBrickBuildPiece("1x1", new Vector3(0.5f, 1f, 0.5f), 3, brick1x1); AddBrickBuildPiece("2x1", new Vector3(1f, 1f, 0.5f), 4, brick2x1); AddBrickBuildPiece("4x2", new Vector3(2f, 2f, 0.5f), 6, brick4x2); AddBrickBuildPiece("1x2", new Vector3(0.5f, 2f, 0.5f), 5, brick1x2); PrefabManager.OnVanillaPrefabsAvailable -= AddOCDheimBuildPieces; } private void AddBrickBuildPiece(string brickSuffix, Vector3 brickScale, int brickPrice, Texture2D iconTexture) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown string text = "Smooth stone " + brickSuffix; CustomPiece piece = PieceManager.Instance.GetPiece(text); if (piece == null) { GameObject val = PrefabManager.Instance.CreateClonedPrefab("stone_floor_" + brickSuffix, "stone_floor_2x2"); Sprite icon = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), Vector2.zero); val.transform.localScale = brickScale; PieceConfig val2 = new PieceConfig(); val2.Name = text; val2.PieceTable = "Hammer"; val2.Category = "HeavyBuild"; val2.Icon = icon; val2.AddRequirement(new RequirementConfig("Stone", brickPrice, 0, true)); PieceManager.Instance.AddPiece(new CustomPiece(val, false, val2)); } } private void ModVanillaValheimTools() { PrefabManager.Instance.GetPrefab("mud_road_v2").AddComponent<LevelGroundOverlayVisualizer>(); PrefabManager.Instance.GetPrefab("raise_v2").AddComponent<RaiseGroundOverlayVisualizer>(); PrefabManager.Instance.GetPrefab("path_v2").AddComponent<PaveRoadOverlayVisualizer>(); PrefabManager.Instance.GetPrefab("paved_road_v2").AddComponent<PaveRoadOverlayVisualizer>(); PrefabManager.Instance.GetPrefab("cultivate_v2").AddComponent<CultivateOverlayVisualizer>(); PrefabManager.Instance.GetPrefab("replant_v2").AddComponent<SeedGrassOverlayVisualizer>(); } } [HarmonyPatch] public static class PileUpper { [HarmonyPostfix] [HarmonyPatch(typeof(WearNTear))] [HarmonyPatch("Start")] private static void MakePilesAsDurableAsWood(WearNTear __instance) { if (((Object)__instance).name.Contains("pile") || ((Object)__instance).name.Contains("stack")) { __instance.m_supports = true; } } } [HarmonyPatch] public static class RemoveExpensiveUnnecessaryCalls { private static bool ShouldSuppressVanillaValheim() { return (KeyBinder.gridModeEnabled && PrecisePieceSnapper.GridModeRequirementsSatisfied()) || (KeyBinder.snapModeEnabled && PrecisePieceSnapper.SnapModeRequirementsSatisfied()); } [HarmonyTranspiler] [HarmonyPatch(typeof(Player))] [HarmonyPatch("UpdatePlacementGhost")] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { bool foundCodeToRemove = false; bool foundCodeToReplace = false; foreach (CodeInstruction instruction in instructions) { foundCodeToRemove = (foundCodeToRemove ? foundCodeToRemove : (instruction.opcode == OpCodes.Ldstr && (string)instruction.operand == "AltPlace")); if (foundCodeToRemove && !foundCodeToReplace) { foundCodeToReplace = (foundCodeToReplace ? foundCodeToReplace : (instruction.opcode == OpCodes.Call)); if (!foundCodeToReplace) { instruction.opcode = OpCodes.Nop; instruction.operand = null; yield return instruction; continue; } instruction.opcode = OpCodes.Call; instruction.operand = SymbolExtensions.GetMethodInfo((Expression<Action>)(() => ShouldSuppressVanillaValheim())); yield return instruction; } else { yield return instruction; } } } } [HarmonyPatch] public static class PrecisePieceSnapper { private const float NeighbourhoodSize = 2.5f; private static readonly int PiecesOnly = LayerMask.GetMask(new string[1] { "piece" }); private static readonly int LayerMask = PlayerHelpers.player.m_placeRayMask - LayerMask.GetMask(new string[1] { "piece_nonsolid" }); private static readonly Collider[] NeighbourColliders = (Collider[])(object)new Collider[255]; private static readonly List<Piece> NeighbourPieces = new List<Piece>(); public static bool GridModeRequirementsSatisfied() { return PlayerHelpers.player.HasBuildPieceEquipped() || PlayerHelpers.player.HasOverlayVisible(); } public static bool SnapModeRequirementsSatisfied() { return (Object)(object)PieceHelpers.buildPiece != (Object)null && (PieceHelpers.buildPiece.Type() != 0 || KeyBinder.precisionMode == PrecisionMode.SUPERIOR); } private static bool ShouldUsePlayerPositionAsGroundLevelReference() { return PlayerHelpers.player.HasLevelGroundTerraformToolEquipped() && KeyBinder.snapModeEnabled; } [HarmonyPostfix] [HarmonyPatch(typeof(Player))] [HarmonyPatch("UpdatePlacementGhost")] private static void SnapBuildPiece() { if (KeyBinder.gridModeEnabled && GridModeRequirementsSatisfied()) { SnapToWorldGrid(PieceHelpers.buildPiece); } else if (KeyBinder.snapModeEnabled && SnapModeRequirementsSatisfied()) { SnapToNeighbourPiece(PieceHelpers.buildPiece); } } private static void SnapToWorldGrid(Piece buildPiece) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Vector3 playerPoV = DeterminePlayerPoV(); int precisionMode = (int)KeyBinder.precisionMode; var (num, num2) = SnapToWorldGrid(playerPoV, precisionMode); if (ShouldUsePlayerPositionAsGroundLevelReference()) { ((Component)buildPiece).transform.position = new Vector3(num, PlayerHelpers.playerPos.y, num2); } else { Vector2 drillCoords = default(Vector2); ((Vector2)(ref drillCoords))..ctor(num, num2); Vector3 neighbourPieceExit = ((PlayerHelpers.player.HasOverlayVisible() || buildPiece.IsGroundBound()) ? PrecisionDrill.DrillDownTillGround(drillCoords) : PrecisionDrill.DrillDownTillFloor(drillCoords, ((Component)buildPiece).transform.position.y)); SnapExternallyHelper(buildPiece, neighbourPieceExit, Vector3.up); } if (PlayerHelpers.player.HasOverlayVisible()) { FixVanillaValheimBugWithSpinningTerrainModificationVFX(); } } private static (float xOnGrid, float zOnGrid) SnapToWorldGrid(Vector3 playerPoV, int precision) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) float item; float item2; if (PlayerHelpers.player.HasColorBrushEquipped()) { float num = Mathf.Floor(playerPoV.x / 64f) * 64f; float num2 = Mathf.Floor(playerPoV.z / 64f) * 64f; float num3 = num - 32f; float num4 = num2 - 32f; float num5 = playerPoV.x - num3; float num6 = playerPoV.z - num4; item = num3 + Mathf.Floor(num5 / (64f / 65f)) * (64f / 65f) + 32f / 65f; item2 = num4 + Mathf.Floor(num6 / (64f / 65f)) * (64f / 65f) + 32f / 65f; } else { item = Mathf.Round(playerPoV.x * (float)precision) / (float)precision; item2 = Mathf.Round(playerPoV.z * (float)precision) / (float)precision; } return (item, item2); } private static void SnapToNeighbourPiece(Piece buildPiece) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Vector3 playerPoV = DeterminePlayerPoV(); List<Piece> neighbourPieces = FindNeighbourPieces(playerPoV); switch (buildPiece.Type()) { case PieceType.CONSTRUCTION: SnapInternally(buildPiece, neighbourPieces); break; case PieceType.FURNITURE: case PieceType.TABLE: SnapExternally(buildPiece, neighbourPieces, playerPoV); break; } } private static void SnapInternally(Piece buildPiece, List<Piece> neighbourPieces) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) SnapTree.TraversalResult? traversalResult = ((KeyBinder.precisionMode == PrecisionMode.ORDINARY) ? SnapTree.FindNearestOrdinaryPrecisionSnapNodeCombinationOf(buildPiece, neighbourPieces) : SnapTree.FindNearestSuperiorPrecisionSnapNodeCombinationOf(buildPiece, neighbourPieces)); if (traversalResult.HasValue) { SnapTree.TraversalResult valueOrDefault = traversalResult.GetValueOrDefault(); if (true) { Transform transform = ((Component)buildPiece).transform; transform.position += (Vector3)valueOrDefault.neighbourSnapNode - valueOrDefault.buildPieceSnapNode; } } } private static void SnapExternally(Piece buildPiece, List<Piece> neighbourPieces, Vector3 playerPoV) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) SnapTree.TraversalResult? traversalResult = ((KeyBinder.precisionMode == PrecisionMode.ORDINARY) ? SnapTree.FindNearestOrdinaryPrecisionSnapNodeTo(playerPoV, neighbourPieces) : SnapTree.FindNearestSuperiorPrecisionSnapNodeTo(playerPoV, neighbourPieces)); if (!traversalResult.HasValue) { return; } SnapTree.TraversalResult valueOrDefault = traversalResult.GetValueOrDefault(); if (true) { var (val, perpendicularToPlayerPoV) = DetermineNeighbourPieceExit(valueOrDefault.neighbourSnapNode, valueOrDefault.neighbourPiece); if (!buildPiece.IsGroundBound()) { SnapExternallyHelper(buildPiece, val, perpendicularToPlayerPoV); } else { ((Component)buildPiece).transform.position = val; } } } private static void SnapExternallyHelper(Piece buildPiece, Vector3 neighbourPieceExit, Vector3 perpendicularToPlayerPoV) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) ((Component)buildPiece).transform.position = neighbourPieceExit + perpendicularToPlayerPoV * 10f; Vector3 buildPieceExit = DeterminePieceExit(buildPiece, neighbourPieceExit); SnapPiecesByExits(buildPiece, buildPieceExit, neighbourPieceExit, perpendicularToPlayerPoV); } private static (Vector3, Vector3) DetermineNeighbourPieceExit(SnapNode neighbourSnapNode, Piece neighbourPiece) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) Vector3 snapNode = PokeToMiddle(neighbourSnapNode, neighbourPiece); Vector3 val = DeterminePerpendicularToPlayerPoVOn(snapNode); Vector3 observer = (Vector3)neighbourSnapNode + val; Vector3 item = DeterminePieceExit(neighbourPiece, observer); return (item, val); } private static Vector3 DeterminePlayerPoV() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 forward = ((Component)GameCamera.instance).transform.forward; RaycastHit val = default(RaycastHit); Physics.Raycast(position, forward, ref val, 250f, LayerMask); return ((RaycastHit)(ref val)).point; } private static Vector3 DeterminePerpendicularToPlayerPoVOn(Vector3 snapNode) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 val = snapNode - position; RaycastHit val2 = default(RaycastHit); Physics.Raycast(position, val, ref val2, 250f, LayerMask); return ((RaycastHit)(ref val2)).normal; } private static List<Piece> FindNeighbourPieces(Vector3 playerPoV) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) NeighbourPieces.Clear(); int num = Physics.OverlapSphereNonAlloc(playerPoV, 2.5f, NeighbourColliders, PiecesOnly); for (int i = 0; i < num; i++) { Collider val = NeighbourColliders[i]; Transform root = ((Component)val).transform.root; Piece val2 = ((root != null) ? ((Component)root).GetComponentInChildren<Piece>() : null); if ((Object)(object)val2 != (Object)null && val2.Type().IsSnappable()) { NeighbourPieces.Add(val2); } } return NeighbourPieces; } private static Vector3 DeterminePieceExit(Piece piece, Vector3 observer) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; Vector3 result = ((Component)piece).transform.position; Collider[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Collider>(); Collider[] array = componentsInChildren; foreach (Collider val in array) { if (!val.enabled || val.isTrigger) { continue; } MeshCollider val2 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if ((Object)(object)val2 == (Object)null || val2.convex) { Vector3 val3 = val.ClosestPoint(observer); float num2 = Vector3.Distance(observer, val3); if (num2 < num) { result = val3; num = num2; } } } return result; } private static Vector3 PokeToMiddle(Vector3 snapNode, Piece piece) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)piece).transform.position - snapNode; Vector3 val2 = ((Vector3)(ref val)).normalized * 0.05f; return snapNode + val2; } private static void SnapPiecesByExits(Piece buildPiece, Vector3 buildPieceExit, Vector3 neighbourPieceEntry, Vector3 perpendicularToNeighbourPiece) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Vector3 val = neighbourPieceEntry - buildPieceExit; Vector3 val2 = Vector3.Project(val, perpendicularToNeighbourPiece); Transform transform = ((Component)buildPiece).transform; transform.position += val2; } private static void FixVanillaValheimBugWithSpinningTerrainModificationVFX() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) ((Component)PieceHelpers.buildPiece).transform.rotation = Quaternion.Euler(0f, 0f, 0f); } } [HarmonyPatch] public static class PreciseTerrainModifier { private const int AoESize = 1; public const int HTilesPerChunk = 64; private const int PTilesPerChunk = 65; public const float HalfPTilesPerChunk = 32f; public const float PTileSize = 64f / 65f; [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("InternalDoOperation")] private static bool Prefix(Vector3 pos, Settings modifier, Heightmap ___m_hmap, ref float[] ___m_levelDelta, ref float[] ___m_smoothDelta, ref Color[] ___m_paintMask, ref bool[] ___m_modifiedHeight, ref bool[] ___m_modifiedPaint) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!modifier.m_level && !modifier.m_raise && !modifier.m_smooth && !modifier.m_paintCleared) { RemoveTerrainModifications(pos, ___m_hmap, ref ___m_levelDelta, ref ___m_smoothDelta, ref ___m_modifiedHeight); RecolorTerrain(pos, (PaintType)3, ___m_hmap, ref ___m_paintMask, ref ___m_modifiedPaint); } return true; } public static void SmoothenTerrain(Vector3 worldPos, Heightmap hMap, TerrainComp compiler, ref float[] smoothΔ, ref bool[] modifiedHeight) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Logger.Debug(() => "[INIT] Smooth Terrain Modification"); int xPos = default(int); int yPos = default(int); hMap.WorldToVertex(worldPos, ref xPos, ref yPos); float referenceH = worldPos.y - ((Component)compiler).transform.position.y; Logger.Debug(() => $"worldPos: {worldPos}, xPos: {xPos}, yPos: {yPos}, referenceH: {referenceH}"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int x = minVal; x <= maxVal; x++) { for (int y = minVal2; y <= maxVal2; y++) { int num = y * 65 + x; float tileH = hMap.GetHeight(x, y); float Δh = referenceH - tileH; float oldΔh = smoothΔ[num]; float newΔh = oldΔh + Δh; float roundedNewΔh = RoundToTwoDecimals(tileH, oldΔh, newΔh); float limΔh = Mathf.Clamp(roundedNewΔh, -1f, 1f); smoothΔ[num] = limΔh; modifiedHeight[num] = true; Logger.Debug(() => $"tilePos: ({x}, {y}), tileH: {tileH}, Δh: {Δh}, oldΔh: {oldΔh}, newΔh: {newΔh}, roundedNewΔh: {roundedNewΔh}, limΔh: {limΔh}"); } } Logger.Debug(() => "[SUCCESS] Smooth Terrain Modification"); } public static void RaiseTerrain(Vector3 worldPos, Heightmap hMap, TerrainComp compiler, float power, ref float[] levelΔ, ref float[] smoothΔ, ref bool[] modifiedHeight) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) Logger.Debug(() => "[INIT] Raise Terrain Modification"); int xPos = default(int); int yPos = default(int); hMap.WorldToVertex(worldPos, ref xPos, ref yPos); float referenceH = worldPos.y - ((Component)compiler).transform.position.y + power; Logger.Debug(() => $"worldPos: {worldPos}, xPos: {xPos}, yPos: {yPos}, power: {power}, referenceH: {referenceH}"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int x = minVal; x <= maxVal; x++) { for (int y = minVal2; y <= maxVal2; y++) { int num = y * 65 + x; float tileH = hMap.GetHeight(x, y); float Δh = referenceH - tileH; if (Δh >= 0f) { float oldLevelΔ = levelΔ[num]; float oldSmoothΔ = smoothΔ[num]; float newLevelΔ = oldLevelΔ + oldSmoothΔ + Δh; float newSmoothΔ = 0f; float roundedNewLevelΔ = RoundToTwoDecimals(tileH, oldLevelΔ + oldSmoothΔ, newLevelΔ + newSmoothΔ); float limitedNewLevelΔ = Mathf.Clamp(roundedNewLevelΔ, -16f, 16f); levelΔ[num] = limitedNewLevelΔ; smoothΔ[num] = newSmoothΔ; modifiedHeight[num] = true; Logger.Debug(() => $"tilePos: ({x}, {y}), tileH: {tileH}, Δh: {Δh}, oldLevelΔ: {oldLevelΔ}, oldSmoothΔ: {oldSmoothΔ}, newLevelΔ: {newLevelΔ}, newSmoothΔ: {newSmoothΔ}, roundedNewLevelΔ: {roundedNewLevelΔ}, limitedNewLevelΔ: {limitedNewLevelΔ}"); } else { Logger.Debug(() => "Declined to process tile: Δh < 0!"); Logger.Debug(() => $"tilePos: ({x}, {y}), tileH: {tileH}, Δh: {Δh}"); } } } Logger.Debug(() => "[SUCCESS] Raise Terrain Modification"); } public static void RecolorTerrain(Vector3 worldPos, PaintType paintType, Heightmap hMap, ref Color[] paintMask, ref bool[] modifiedPaint) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Logger.Info(() => "[INIT] Color Terrain Modification 3x3"); Color tileColor = ResolveColor(paintType); PositionRelativeTo(((Component)hMap).transform.position, worldPos, out var xPos, out var yPos); Logger.Info(() => $"worldPos: {worldPos}, chunkPos: {((Component)hMap).transform.position}, relPos: ({xPos}, {yPos})"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int i = minVal; i <= maxVal; i++) { for (int j = minVal2; j <= maxVal2; j++) { ApplyColor(i, j, tileColor, ref paintMask, ref modifiedPaint); } } Logger.Info(() => "[SUCCESS] Color Terrain Modification 3x3"); } private static void RemoveTerrainModifications(Vector3 worldPos, Heightmap hMap, ref float[] levelΔ, ref float[] smoothΔ, ref bool[] modifiedHeight) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Logger.Debug(() => "[INIT] Remove Terrain Modifications"); int xPos = default(int); int yPos = default(int); hMap.WorldToVertex(worldPos, ref xPos, ref yPos); Logger.Debug(() => $"worldPos: {worldPos}, vertexPos: ({xPos}, {yPos})"); FindExtremums(xPos, out var minVal, out var maxVal); FindExtremums(yPos, out var minVal2, out var maxVal2); for (int x = minVal; x <= maxVal; x++) { for (int y = minVal2; y <= maxVal2; y++) { int tileIndex = y * 65 + x; levelΔ[tileIndex] = 0f; smoothΔ[tileIndex] = 0f; modifiedHeight[tileIndex] = false; Logger.Debug(() => $"tilePos: ({x}, {y}), tileIndex: {tileIndex}"); } } Logger.Debug(() => "[SUCCESS] Remove Terrain Modifications"); } private static void FindExtremums(int val, out int minVal, out int maxVal) { minVal = Mathf.Max(0, val - 1); maxVal = Mathf.Min(val + 1, 64); } private static float RoundToTwoDecimals(float oldH, float oldΔh, float newΔh) { float newH = oldH - oldΔh + newΔh; float roundedNewH = Mathf.Round(newH * 100f) / 100f; float roundedNewΔh = roundedNewH - oldH + oldΔh; Logger.Debug(() => $"oldH: {oldH}, oldΔH: {oldΔh}, newΔH: {newΔh}, newH: {newH}, roundedNewH: {roundedNewH}, roundedNewΔh: {roundedNewΔh}"); return roundedNewΔh; } private static void PositionRelativeTo(Vector3 chunkMid, Vector3 worldPos, out int x, out int y) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Vector3 val = chunkMid - new Vector3(32f, 0f, 32f); Vector3 val2 = worldPos - val; x = Mathf.FloorToInt(val2.x / (64f / 65f)); y = Mathf.FloorToInt(val2.z / (64f / 65f)); } private static Color ResolveColor(PaintType paintType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected I4, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) return (Color)((int)paintType switch { 0 => Color.red, 2 => Color.blue, 1 => Color.green, _ => Color.black, }); } private static void ApplyColor(int x, int y, Color tileColor, ref Color[] paintMask, ref bool[] modifiedPaint) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) int tileIndex = y * 65 + x; paintMask[tileIndex] = tileColor; modifiedPaint[tileIndex] = tileColor != Color.black; Logger.Info(() => $"tilePos: ({x}, {y}), tileIndex: {tileIndex}, tileColor: {tileColor}"); } } [HarmonyPatch] public static class PreciseSmoothTerrainModification { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("SmoothTerrain")] private static bool Prefix(Vector3 worldPos, float radius, bool square, float power, TerrainComp __instance, Heightmap ___m_hmap, ref float[] ___m_smoothDelta, ref bool[] ___m_modifiedHeight) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (ClientSideGridModeOverride.IsGridModeEnabled(radius)) { PreciseTerrainModifier.SmoothenTerrain(worldPos, ___m_hmap, __instance, ref ___m_smoothDelta, ref ___m_modifiedHeight); return false; } return true; } } [HarmonyPatch] public static class PreciseRaiseTerrainModification { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("RaiseTerrain")] private static bool Prefix(Vector3 worldPos, float radius, float delta, bool square, float power, TerrainComp __instance, Heightmap ___m_hmap, ref float[] ___m_levelDelta, ref float[] ___m_smoothDelta, ref bool[] ___m_modifiedHeight) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (ClientSideGridModeOverride.IsGridModeEnabled(radius)) { PreciseTerrainModifier.RaiseTerrain(worldPos, ___m_hmap, __instance, delta, ref ___m_levelDelta, ref ___m_smoothDelta, ref ___m_modifiedHeight); return false; } return true; } } [HarmonyPatch] public static class PreciseColorTerrainModification { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("PaintCleared")] private static bool Prefix(Vector3 worldPos, float radius, PaintType paintType, bool heightCheck, bool apply, Heightmap ___m_hmap, ref Color[] ___m_paintMask, ref bool[] ___m_modifiedPaint) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (ClientSideGridModeOverride.IsGridModeEnabled(radius)) { PreciseTerrainModifier.RecolorTerrain(worldPos, paintType, ___m_hmap, ref ___m_paintMask, ref ___m_modifiedPaint); return false; } return true; } } [HarmonyPatch] public static class ClientSideGridModeOverride { [HarmonyPrefix] [HarmonyPatch(typeof(TerrainComp))] [HarmonyPatch("ApplyOperation")] private static bool Prefix(TerrainOp modifier) { if (KeyBinder.gridModeEnabled) { if (modifier.m_settings.m_smooth) { modifier.m_settings.m_smoothRadius = float.NegativeInfinity; } if (modifier.m_settings.m_raise && modifier.m_settings.m_raiseDelta >= 0f) { modifier.m_settings.m_raiseRadius = float.NegativeInfinity; modifier.m_settings.m_raiseDelta = GroundLevelSpinner.RaiseGroundSpinner.value; } if (modifier.m_settings.m_raise && modifier.m_settings.m_raiseDelta < 0f) { modifier.m_settings.m_raiseDelta = GroundLevelSpinner.LowerGroundSpinner.value; } if (modifier.m_settings.m_paintCleared) { modifier.m_settings.m_paintRadius = float.NegativeInfinity; } } return true; } public static bool IsGridModeEnabled(float radius) { return float.IsNegativeInfinity(radius); } } public static class PrecisionDrill { public const float DropFromExosphere = 250f; private const int MaxDrillsInMemory = 4096; private const float DrillSize = 0.01f; private static readonly int GroundLayerMask = LayerMask.GetMask(new string[1] { "terrain" }); private static readonly int FloorLayerMask = LayerMask.GetMask(new string[3] { "terrain", "piece", "static_solid" }); private static Func<Vector2, Vector2> roundDrillCoords => (Vector2 drillCoords) => new Vector2(Mathf.Round(drillCoords.x * 10f) / 10f, Mathf.Round(drillCoords.y * 10f) / 10f); public static IRefreshableMemoryRepo<Vector2, Vector3> groundLevels => new MemoryRepo<Vector2, Vector3>(DrillDownToGround, 4096).EvictionPolicy(TimeSpan.FromMilliseconds(125.0)); public static IRefreshableMemoryRepo<Vector2, List<float>> floorLevels => new MemoryRepo<Vector2, List<float>>((Vector2 drillCoords) => DrillDownFloors(drillCoords), roundDrillCoords, 4096).EvictionPolicy(TimeSpan.FromMilliseconds(500.0)); public static Vector3 DrillDownTillGround(Vector2 drillCoords) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return groundLevels.LookUp(drillCoords); } private static Vector3 DrillDownToGround(Vector2 drillCoords) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val = WhereToDrillFrom(drillCoords); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 250f, GroundLayerMask)) { return ((RaycastHit)(ref val2)).point; } return FallBack(drillCoords); } private static Vector3 WhereToDrillFrom(Vector2 drillCoords) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return new Vector3(drillCoords.x, 250f, drillCoords.y); } private static Vector3 FallBack(Vector2 drillCoords) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Logger.Warn(() => $"[FAILED] Precision Drill for: {drillCoords}"); return new Vector3(drillCoords.x, ((Component)PlayerHelpers.player).transform.position.y, drillCoords.y); } public static Vector3 DrillDownTillFloor(Vector2 drillCoords, float referenceLevel) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) List<float> list = floorLevels.LookUp(drillCoords); float num = list[0]; float num2 = Math.Abs(referenceLevel - num); foreach (float item in list) { float num3 = Math.Abs(referenceLevel - item); if (num3 < num2) { num2 = num3; num = item; } } return new Vector3(drillCoords.x, num, drillCoords.y); } private static List<float> DrillDownFloors(Vector2 drillCoords, float drillTill = 250f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Vector3 val = WhereToDrillFrom(drillCoords); List<float> list = new List<float>(); float roofLevel = val.y; RaycastHit val2 = default(RaycastHit); while (Physics.SphereCast(val, 0.01f, Vector3.down, ref val2, drillTill, FloorLayerMask)) { float y = ((RaycastHit)(ref val2)).point.y; if (!ShouldSkipDueToInsufficientSize(((RaycastHit)(ref val2)).collider) && !ShouldSkipDueToInsufficientRoom(y, roofLevel)) { list.Add(y); } val.y -= ((RaycastHit)(ref val2)).distance + 0.0001f; drillTill -= ((RaycastHit)(ref val2)).distance + 0.0001f; roofLevel = y; } return list; } private static bool ShouldSkipDueToInsufficientSize(Collider collider) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Piece componentInChildren = ((Component)((Component)collider).transform.root).GetComponentInChildren<Piece>(); if ((Object)(object)componentInChildren != (Object)null) { return false; } Bounds bounds = collider.bounds; return ((Bounds)(ref bounds)).max.x - ((Bounds)(ref bounds)).min.x < 0.5f || ((Bounds)(ref bounds)).max.z - ((Bounds)(ref bounds)).min.z < 0.5f; } private static bool ShouldSkipDueToInsufficientRoom(float floorLevel, float roofLevel) { return roofLevel - floorLevel < 0.5f; } } public enum PrecisionMode { ORDINARY = 1, SUPERIOR } public readonly struct Box : ISide { private const double Epsilon = 1E-08; private char name { get; } private Vector3 minMinSnapNode { get; } private Vector3 minMaxSnapNode { get; } private Vector3 maxMinSnapNode { get; } private Vector3 maxMaxSnapNode { get; } private SnapNode.Type primarySnapNodeType { get; } public Box(char name, Vector3 minMinSnapNode, Vector3 minMaxSnapNode, Vector3 maxMinSnapNode, Vector3 maxMaxSnapNode) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) this.name = name; this.minMinSnapNode = minMinSnapNode; this.minMaxSnapNode = minMaxSnapNode; this.maxMinSnapNode = maxMinSnapNode; this.maxMaxSnapNode = maxMaxSnapNode; primarySnapNodeType = SnapNode.Type.PRIMARY; } public Box(Piece piece, Vector2 shift, char name = 'A') { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) this.name = name; Vector3 val = piece.TopMiddle(); minMinSnapNode = val + ((Component)piece).transform.rotation * new Vector3(0f - shift.x, 0f, 0f - shift.y); minMaxSnapNode = val + ((Component)piece).transform.rotation * new Vector3(0f - shift.x, 0f, shift.y); maxMinSnapNode = val + ((Component)piece).transform.rotation * new Vector3(shift.x, 0f, 0f - shift.y); maxMaxSnapNode = val + ((Component)piece).transform.rotation * new Vector3(shift.x, 0f, shift.y); primarySnapNodeType = SnapNode.Type.IMPOSED; } public void FillUp(HashSet<SnapNode> snapNodes) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) Vector3 dimensionΔ = minMaxSnapNode - minMinSnapNode; Vector3 dimensionΔ2 = maxMinSnapNode - minMinSnapNode; (Vector3, int) tuple = RecursiveSplit(dimensionΔ); Vector3 item = tuple.Item1; int item2 = tuple.Item2; (Vector3, int) tuple2 = RecursiveSplit(dimensionΔ2); Vector3 item3 = tuple2.Item1; int item4 = tuple2.Item2; double num = Math.Pow(2.0, item2) + 1.0; double num2 = Math.Pow(2.0, item4) + 1.0; for (int i = 0; (double)i < num; i++) { for (int j = 0; (double)j < num2; j++) { Vector3 position = minMinSnapNode + item * (float)i + item3 * (float)j; if ((i == 0 || Math.Abs((double)i - (num - 1.0)) < 1E-08) && (j == 0 || Math.Abs((double)j - (num2 - 1.0)) < 1E-08)) { snapNodes.Add(new SnapNode(position, primarySnapNodeType, SnapNode.Precision.ORDINARY)); } else if ((float)i % 2f == 0f && (float)j % 2f == 0f) { snapNodes.Add(new SnapNode(position, SnapNode.Type.DERIVED, SnapNode.Precision.ORDINARY)); } else { snapNodes.Add(new SnapNode(position, SnapNode.Type.DERIVED, SnapNode.Precision.SUPERIOR)); } } } } private (Vector3, int) RecursiveSplit(Vector3 dimensionΔ, int splitLevel = 0) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref dimensionΔ)).magnitude > 0.75f) { return RecursiveSplit(dimensionΔ * 0.5f, ++splitLevel); } return (dimensionΔ, splitLevel); } public override string ToString() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) return $"Box {name}: ({minMinSnapNode}, {minMaxSnapNode}, {maxMinSnapNode}, {maxMaxSnapNode})"; } } public readonly struct Circle : ISide { private const int CircleDivisions = 8; private char name { get; } private Vector3 midSnapNode { get; } private Vector2 radial { get; } public Circle(Piece piece, Vector2 radial, char name = 'A') { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) this.name = name; this.radial = radial; midSnapNode = piece.TopMiddle(); } public void FillUp(HashSet<SnapNode> snapNodes) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 8; i++) { Vector3 val = Quaternion.Euler(new Vector3(0f, 45f * (float)i, 0f)) * Vector2.op_Implicit(radial); Vector3 val2 = midSnapNode + val; snapNodes.Add(new SnapNode(midSnapNode, SnapNode.Type.IMPOSED, SnapNode.Precision.ORDINARY)); snapNodes.Add(new SnapNode(val2, SnapNode.Type.IMPOSED, SnapNode.Precision.ORDINARY)); SnapNode.RecursiveSplit(midSnapNode, val2, snapNodes); } } public override string ToString() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) return $"Circle {name}: {midSnapNode} + {radial} * quaternion rotation"; } } public interface ISide { void FillUp(HashSet<SnapNode> snapNodes); } public readonly struct Line : ISide { private char name { get; } private Vector3 minSnapNode { get; } private Vector3 maxSnapNode { get; } public void FillUp(HashSet<SnapNode> snapNodes) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) SnapNode.RecursiveSplit(minSnapNode, maxSnapNode, snapNodes); } public Line(char name, Vector3 minSnapNode, Vector3 maxSnapNode) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) this.name = name; this.minSnapNode = minSnapNode; this.maxSnapNode = maxSnapNode; } public override string ToString() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) return $"Line {name}: ({minSnapNode}, {maxSnapNode})"; } } public readonly struct SnapNode : IEquatable<SnapNode> { public enum Type { PRIMARY, IMPOSED, DERIVED } public enum Precision { ORDINARY, SUPERIOR } public const float OrdinaryPrecisionSplitThreshold = 1.5f; public const float SuperiorPrecisionMultiplier = 2f; public Precision precision { get; } private Vector3 position { get; } private Type type { get; } private static bool ShouldSplitInOrdinaryPrecisionMode(Vector3 prevSnapNode, Vector3 nextSnapNode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(prevSnapNode, nextSnapNode) > 1.5f; } private static bool ShouldSplitInSuperiorPrecisionMode(Vector3 prevSnapNode, Vector3 nextSnapNode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(prevSnapNode, nextSnapNode) > 0.75f; } public SnapNode(Vector3 position, Type type, Precision precision) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.position = position; this.type = type; this.precision = precision; } public static void RecursiveSplit(Vector3 snapNodeA, Vector3 snapNodeB, HashSet<SnapNode> snapNodes) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) snapNodes.Add(new SnapNode(snapNodeA, Type.PRIMARY, Precision.ORDINARY)); snapNodes.Add(new SnapNode(snapNodeB, Type.PRIMARY, Precision.ORDINARY)); RecursiveSplitInOrdinaryPrecisionMode(snapNodeA, snapNodeB, snapNodes); } private static void RecursiveSplitInOrdinaryPrecisionMode(Vector3 snapNodeA, Vector3 snapNodeB, HashSet<SnapNode> snapNodes, int splitLevel = 0) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (ShouldSplitInOrdinaryPrecisionMode(snapNodeA, snapNodeB)) { Vector3 midSnapNode = (snapNodeA + snapNodeB) * 0.5f; snapNodes.Add(new SnapNode(midSnapNode, Type.DERIVED, Precision.ORDINARY)); Logger.Debug(delegate { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[4]; int num = splitLevel; splitLevel = num + 1; array[0] = num; array[1] = snapNodeA; array[2] = snapNodeB; array[3] = midSnapNode; return string.Format("[SPLIT LEVEL {0}] Ordinary Precision Child of: {1} & {2}, is: {3}", array); }); RecursiveSplitInOrdinaryPrecisionMode(snapNodeA, midSnapNode, snapNodes, splitLevel); RecursiveSplitInOrdinaryPrecisionMode(midSnapNode, snapNodeB, snapNodes, splitLevel); } else { RecursiveSplitInSuperiorPrecisionMode(snapNodeA, snapNodeB, snapNodes, splitLevel); } } private static void RecursiveSplitInSuperiorPrecisionMode(Vector3 snapNodeA, Vector3 snapNodeB, HashSet<SnapNode> snapNodes, int splitLevel) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (ShouldSplitInSuperiorPrecisionMode(snapNodeA, snapNodeB)) { Vector3 midSnapNode = (snapNodeA + snapNodeB) * 0.5f; snapNodes.Add(new SnapNode(midSnapNode, Type.DERIVED, Precision.SUPERIOR)); Logger.Debug(delegate { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[4]; int num = splitLevel; splitLevel = num + 1; array[0] = num; array[1] = snapNodeA; array[2] = snapNodeB; array[3] = midSnapNode; return string.Format("[SPLIT LEVEL {0}] Superior Precision Child of: {1} & {2}, is: {3}", array); }); RecursiveSplitInSuperiorPrecisionMode(snapNodeA, midSnapNode, snapNodes, splitLevel); RecursiveSplitInSuperiorPrecisionMode(midSnapNode, snapNodeB, snapNodes, splitLevel); } } public static implicit operator Vector3(SnapNode snapNode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return snapNode.position; } public override string ToString() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) return $"{type} Snap Node of {precision} precision: {position}"; } public override bool Equals(object other) { return other is SnapNode snapNode && snapNode.Equals(this); } public bool Equals(SnapNode snapNode) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) return snapNode.position == position; } public override int GetHashCode() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Vector3 val = position; return ((object)(Vector3)(ref val)).GetHashCode(); } } public readonly struct SnapTree { public struct TraversalResult { public Vector3 buildPieceSnapNode { get; } public SnapNode neighbourSnapNode { get; } public Piece neighbourPiece { get; } public TraversalResult(Vector3 buildPieceSnapNode, SnapNode neighbourSnapNode, Piece neighbourPiece) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.buildPieceSnapNode = buildPieceSnapNode; this.neighbourSnapNode = neighbourSnapNode; this.neighbourPiece = neighbourPiece; } } private const int ZeroSidesAllowed = 0; private const int OneSideAllowed = 1; private const int SidesOfCube = 6; private const int SidesOfOctagon = 10; private const float SnapThreshold = 1f; private static readonly List<Box> Boxes = new List<Box>(6); private static readonly List<Line> Lines = new List<Line>(10); private static readonly List<ISide> Sides = new List<ISide>(1); private static readonly List<Vector3> HorribleOptimization = new List<Vector3>(1); private static readonly HashSet<SnapNode> ZeroSnapNodes = new HashSet<SnapNode>(0); private static readonly IMemoryRepo<Piece, SnapTree> SnapTrees = new MemoryRepo<Piece, SnapTree>((Piece piece) => new SnapTree(piece), 1024); private static readonly Func<SnapNode.Precision, bool> OrdinaryPrecisionOnly = (SnapNode.Precision precision) => precision == SnapNode.Precision.ORDINARY; private static readonly Func<SnapNode.Precision, bool> OrdinaryAndSuperiorPrecision = (SnapNode.Precision precision) => precision == SnapNode.Precision.ORDINARY || precision == SnapNode.Precision.SUPERIOR; private HashSet<SnapNode> snapNodes { get; } private static bool FormValidTwoDimensionalBoxSide(Vector3 snapNodeA, Vector3 snapNodeB, Vector3 snapNodeC, Vector3 snapNodeD) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) return snapNodeA != snapNodeB && snapNodeA != snapNodeC && snapNodeB + snapNodeC - snapNodeA == snapNodeD; } private static Func<Vector3, Vector3, Vector3, Vector3, bool> FormValidThreeDimensionalBoxSide(Piece piece) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector3 pieceMid = ((Component)piece).transform.position; return delegate(Vector3 snapNodeA, Vector3 snapNodeB, Vector3 snapNodeC, Vector3 snapNodeD) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (snapNodeA + snapNodeD) * 0.5f; return FormValidTwoDimensionalBoxSide(snapNodeA, snapNodeB, snapNodeC, snapNodeD) && pieceMid != val; }; } private static bool LiesOnVerticalMiddle(Vector3 snapNode, Piece piece) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return Mathf.Approximately(snapNode.x, ((Component)piece).transform.position.y); } private static bool LiesOnHorizontalMiddle(Vector3 snapNode, Piece piece) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) return Mathf.Approximately(snapNode.x, ((Component)piece).transform.position.x) && Mathf.Approximately(snapNode.z, ((Component)piece).transform.position.z); } private static bool LiesOnSameVerticalSide(Vector3 snapNodeA, Vector3 snapNodeB) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) return Mathf.Approximately(snapNodeA.x, snapNodeB.x) && !Mathf.Approximately(snapNodeA.y, snapNodeB.y) && Mathf.Approximately(snapNodeA.z, snapNodeB.z); } private static bool LiesOnSameHorizontalSide(Vector3 snapNodeA, Vector3 snapNodeB) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return !Mathf.Approximately(snapNodeA.y, snapNodeB.y); } private SnapTree(Piece piece) { Logger.Debug(() => $"[INIT] SNAP TREE CONSTRUCTION of piece: '{piece.m_name}' {((Component)piece).transform.position}"); snapNodes = DeriveSnapNodesFrom(piece); SnapTree tree = this; Logger.Debug(() => "SNAP NODES: " + string.Join(", ", tree.snapNodes)); Logger.Debug(() => $"[SUCCESS] SNAP TREE CONSTRUCTION of piece: '{piece.m_name}' {((Component)piece).transform.position}"); } public static TraversalResult? FindNearestOrdinaryPrecisionSnapNodeTo(Vector3 referencePosition, List<Piece> pieces) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FindNearestSnapNodeTo(referencePosition, pieces, OrdinaryPrecisionOnly); } public static TraversalResult? FindNearestSuperiorPrecisionSnapNodeTo(Vector3 referencePosition, List<Piece> pieces) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FindNearestSnapNodeTo(referencePosition, pieces, OrdinaryAndSuperiorPrecision); } public static TraversalResult? FindNearestOrdinaryPrecisionSnapNodeCombinationOf(Piece buildPiece, List<Piece> neighbourPieces) { return FindNearestSnapNodeTo(buildPiece.PrimarySnapNodes(), neighbourPieces, OrdinaryPrecisionOnly); } public static TraversalResult? FindNearestSuperiorPrecisionSnapNodeCombinationOf(Piece buildPiece, List<Piece> neighbourPieces) { return FindNearestSnapNodeTo(buildPiece.PrimarySnapNodes(), neighbourPieces, OrdinaryAndSuperiorPrecision); } private static HashSet<SnapNode> DeriveSnapNodesFrom(Piece piece) { switch (piece.Type()) { case PieceType.CONSTRUCTION: switch (piece.Shape()) { case PieceShape.LINE: return DeriveSnapNodesFrom(piece, DeriveLineFrom); case PieceShape.BOX: return DeriveSnapNodesFrom(piece, DeriveBoxFrom); case PieceShape.CUBE: return DeriveSnapNodesFrom(piece, DeriveSidesFromCube); case PieceShape.CYLINDER: return DeriveSnapNodesFrom(piece, DeriveSidesFromCylinder); case PieceShape.UNDEFINED: return DeriveSnapNodesFrom(piece, DeriveSidesFromUndefined); } break; case PieceType.FURNITURE: return ZeroSnapNodes; case PieceType.TABLE: return DeriveSnapNodesFrom(piece, ImposeTopSideOn); } throw new InvalidOperationException("This is supposedly mathematically impossible :D"); } private static HashSet<SnapNode> DeriveSnapNodesFrom<T>(Piece piece, Func<Piece, List<T>> deriveSidesFrom) where T : ISide { List<T> sides = deriveSidesFrom(piece); Logger.Debug(() => "SIDES: " + string.Join(", ", sides)); HashSet<SnapNode> result = new HashSet<SnapNode>(255); foreach (T item in sides) { item.FillUp(result); } return result; } private static List<Line> DeriveLineFrom(Piece piece) { List<Line> sides = DeriveSidesFromUndefined(piece); if (sides.Count != 1) { Logger.Warn(() => $"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {1}, ACTUAL SIDES: {sides.Count}"); } return sides; } private static List<Box> DeriveBoxFrom(Piece piece) { return FindSidesOfBoxOrCube(piece, FormValidTwoDimensionalBoxSide, 1); } private static List<Box> DeriveSidesFromCube(Piece piece) { return FindSidesOfBoxOrCube(piece, FormValidThreeDimensionalBoxSide(piece), 6); } private static List<Box> FindSidesOfBoxOrCube(Piece piece, Func<Vector3, Vector3, Vector3, Vector3, bool> isValidSide, int numberOfSides) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) Boxes.Clear(); char c = 'A'; List<Vector3> list = piece.PrimarySnapNodes(); for (int i = 0; i < list.Count; i++) { for (int j = i + 1; j < list.Count; j++) { for (int k = j + 1; k < list.Count; k++) { for (int l = k + 1; l < list.Count; l++) { if (isValidSide(list[i], list[j], list[k], list[l])) { Boxes.Add(new Box(c++, list[i], list[j], list[k], list[l])); } } } } } if (Boxes.Count != numberOfSides) { Logger.Warn(() => $"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {numberOfSides}, ACTUAL SIDES: {Boxes.Count}"); } return Boxes; } private static List<Line> DeriveSidesFromCylinder(Piece piece) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) Lines.Clear(); char c = 'A'; for (int i = 0; i < piece.PrimarySnapNodes().Count; i++) { Vector3 val = piece.PrimarySnapNodes()[i]; if (LiesOnHorizontalMiddle(val, piece)) { continue; } for (int j = i + 1; j < piece.PrimarySnapNodes().Count; j++) { Vector3 val2 = piece.PrimarySnapNodes()[j]; if (!LiesOnHorizontalMiddle(val2, piece)) { Vector3 snapNode = (val + val2) * 0.5f; if (LiesOnSameVerticalSide(val, val2) && !LiesOnHorizontalMiddle(snapNode, piece)) { Lines.Add(new Line(c++, val, val2)); } else if (LiesOnSameHorizontalSide(val, val2) && LiesOnHorizontalMiddle(snapNode, piece)) { Lines.Add(new Line(c++, val, val2)); } } } } if (Lines.Count != 10) { Logger.Warn(() => $"EXPECTED SIDES on Piece '{piece.m_name}' {((Component)piece).transform.position}: {10}, ACTUAL SIDES: {Lines.Count}"); } return Lines; } private static List<Line> DeriveSidesFromUndefined(Piece piece) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) Lines.Clear(); char c = 'A'; for (int i = 0; i < piece.PrimarySnapNodes().Count; i++) { for (int j = i + 1; j < piece.PrimarySnapNodes().Count; j++) { Lines.Add(new Line(c++, piece.PrimarySnapNodes()[i], piece.PrimarySnapNodes()[j])); } } return Lines; } private static List<ISide> ImposeTopSideOn(Piece piece) { Sides.Clear(); ISide item = piece.TopSide(); Sides.Add(item); return Sides; } private static TraversalResult? FindNearestSnapNodeTo(Vector3 referencePosition, List<Piece> pieces, Func<SnapNode.Precision, bool> isDesired) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) HorribleOptimization.Clear(); HorribleOptimization.Add(referencePosition); return FindNearestSnapNodeTo(HorribleOptimization, pieces, isDesired); } private static TraversalResult? FindNearestSnapNodeTo(List<Vector3> buildPieceSnapNodes, List<Piece> neighborPieces, Func<SnapNode.Precision, bool> isDesired) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; TraversalResult? result = null; foreach (Vector3 buildPieceSnapNode in buildPieceSnapNodes) { foreach (Piece neighborPiece in neighborPieces) { foreach (SnapNode snapNode in SnapTrees.LookUp(neighborPiece).snapNodes) { float num2 = Vector3.Distance(buildPieceSnapNode, (Vector3)snapNode); if (isDesired(snapNode.precision) && num > num2 && num2 < 1f) { num = num2; result = new TraversalResult(buildPieceSnapNode, snapNode, neighborPiece); } } } } return result; } } public static class Logger { private static LogLevel logLevel => (LogLevel)32; public static void Debug(Func<string> func) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 32) { Logger.LogDebug((object)func()); } } public static void Info(Func<string> func) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)logLevel >= 16) { Logger.LogInfo((object)func()); } } public static void Warn(Func<string> func) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)logLevel >= 4) { Logger.LogWarning((object)func()); } } } public interface IMemoryRepo<K, V> { V LookUp(K key); } public interface IRefreshableMemoryRepo<K, V> : IMemoryRepo<K, V>, IRefresherable { } public class MemoryRepo<K, TK, V> : IMemoryRepo<K, V> { private class TimeBombMemoryRepo : IRefreshableMemoryRepo<K, V>, IMemoryRepo<K, V>, IRefresherable { private MemoryRepo<K, TK, V> innerMemoryRepo { get; } private TimeSpan explosionTime { get; } private Queue<Timed> timeBomb { get; } public TimeBombMemoryRepo(MemoryRepo<K, TK, V> innerMemoryRepo, TimeSpan explosionTime) { timeBomb = new Queue<Timed>(); this.explosionTime = explosionTime; this.innerMemoryRepo = innerMemoryRepo; } public V LookUp(K key) { TK key2 = innerMemoryRepo.transformer(key); if (!innerMemoryRepo.kvs.ContainsKey(key2)) { timeBomb.Enqueue(new Timed(key2, Time.time + (float)explosionTime.TotalSeconds)); } return innerMemoryRepo.LookUp(key); } public void Refresh() { while (timeBomb.Count > 0 && timeBomb.Peek().explosionTime < Time.time) { Timed boom = timeBomb.Dequeue(); innerMemoryRepo.kvs.Remove(boom.key); Logger.Debug(() => $"[MEMORY REPO EVICTION] on key: {boom.key}"); } } } private struct Timed { public float explosionTime { get; } public TK key { get; } public Timed(TK key, float explosionTime) { this.key = key; this.explosionTime = explosionTime; } } protected Func<K, V> producer { get; } private Dictionary<TK, V> kvs { get; } private Func<K, TK> transformer { get; } public MemoryRepo(Func<K, V> producer, Func<K, TK> transformer, int capacity) { this.producer = producer; this.transformer = transformer; kvs = new Dictionary<TK, V>(capacity); } public V LookUp(K key) { TK val = transformer(key); bool miss = !kvs.ContainsKey(val); Logger.Debug(() => string.Format("[MEMORY REPO {0}] on key: {1}", miss ? "MISS" : "HIT", key)); if (miss) { kvs[val] = ProduceVal(key, val); } return kvs[val]; } public IRefreshableMemoryRepo<K, V> EvictionPolicy(TimeSpan explosionTime) { return new TimeBombMemoryRepo(this, explosionTime); } protected virtual V ProduceVal(K key, TK _) { return producer(key); } } public class MemoryRepo<K, V> : MemoryRepo<K, K, V> { public MemoryRepo(Func<K, V> producer, Func<K, K> transformer, int capacity) : base(producer, transformer, capacity) { } public MemoryRepo(Func<K, V> producer, int capacity) : this(producer, (Func<K, K>)((K key) => key), capacity) { } protected override V ProduceVal(K _, K transformedKey) { return base.producer(transformedKey); } } public static class PieceHelpers { private static readonly IMemoryRepo<Piece, Bounds> PieceSizes = new MemoryRepo<Piece, string, Bounds>(BoundsOf, (Piece piece) => piece.m_name, 255); private static readonly IMemoryRepo<Piece, PieceType> PieceTypes = new MemoryRepo<Piece, string, PieceType>(TypeOf, (Piece piece) => piece.m_name, 255); private static readonly IMemoryRepo<Piece, PieceShape> PieceShapes = new MemoryRepo<Piece, string, PieceShape>(ShapeOf, (Piece piece) => piece.m_name, 255); private static readonly Dictionary<string, Func<Piece, ISide>> Tables = new Dictionary<string, Func<Piece, ISide>> { ["$piece_table_oak"] = (Piece piece) => new Box(piece, new Vector2(3f, 0.8f)), ["$piece_blackmarble_table"] = (Piece piece) => new Box(piece, new Vector2(1.15f, 0.5f)), ["$piece_table"] = (Piece piece) => new Box(piece, new Vector2(1.1f, 0.475f)), ["$piece_table_round"] = (Piece piece) => new Circle(piece, new Vector2(1.15f, 0f)) }; private static readonly List<Transform> PrimarySPs = new List<Transform>(); private static readonly List<Vector3> PrimarySNs = new List<Vector3>(); public static Piece buildPiece { get { GameObject placementGhost = PlayerHelpers.player.m_placementGhost; return (placementGhost != null) ? placementGhost.GetComponent<Piece>() : null; } } public static Bounds Bounds(this Piece piece) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return PieceSizes.LookUp(piece); } public static PieceType Type(this Piece piece) { return PieceTypes.LookUp(piece); } public static PieceShape Shape(this Piece piece) { return PieceShapes.LookUp(piece); } public static ISide TopSide(this Piece piece) { return Tables[piece.m_name](piece); } public static bool IsGroundBound(this Piece piece) { return piece.m_groundPiece || piece.m_clipGround || piece.m_clipEverything; } public static List<Vector3> PrimarySnapNodes(this Piece piece) { piece.FlushPrimarySnapNodes(); piece.PopulatePrimarySnapNodes(); return PrimarySNs; } private static void FlushPrimarySnapNodes(this Piece _) { PrimarySPs.Clear(); PrimarySNs.Clear(); Logger.Debug(() => "[FLUSHED] Primary Snap Nodes of previous piece"); } private static void PopulatePrimarySnapNodes(this Piece piece) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) piece.GetSnapPoints(PrimarySPs); foreach (Transform primarySP in PrimarySPs) { PrimarySNs.Add(((Component)primarySP).transf