Decompiled source of Slides Bot Control v1.2.3
PrioritySet.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("PrioritySet")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Indexed set with optional per-slot priority, conflict resolution, and queue-style operations.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+978d443a8b6a1f288913a375cd36f7569deece8b")] [assembly: AssemblyProduct("PrioritySet")] [assembly: AssemblyTitle("PrioritySet")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace PrioritySet { [Flags] public enum CleanFlags { None = 0, NullValues = 1, NullPriorities = 2, NullValuesAndPriorities = 3 } public enum ConflictResolution { KeepIndex, KeepPriority, ThrowOnConflict } public enum DuplicateValuePolicy { ThrowOnDuplicate, Reject, ReplaceExisting } public enum PlacementIndexBias { HighestValidIndex, LowestValidIndex } [Flags] public enum PrioritySetChangeKind { None = 0, Add = 1, Remove = 2, Reorder = 4, PriorityChange = 8, Clear = 0x10, Clean = 0x20, Sort = 0x40, BulkSetOperation = 0x80, Update = 0x100 } public sealed class PrioritySetChangedEventArgs : EventArgs { public PrioritySetChangeKind ChangeKind { get; } public int? Index { get; } public object? Value { get; } public int? Priority { get; } public PrioritySetChangedEventArgs(PrioritySetChangeKind changeKind, int? index = null, object? value = null, int? priority = null) { ChangeKind = changeKind; Index = index; Value = value; Priority = priority; } } public class PrioritySet<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IReadOnlyList<T>, IReadOnlyCollection<T>, ISet<T> { private sealed class ChangedScope : IDisposable { private readonly PrioritySet<T> _owner; public ChangedScope(PrioritySet<T> owner) { _owner = owner; } public void Dispose() { _owner._changedScopeDepth--; if (_owner._changedScopeDepth == 0) { _owner.FlushPendingChanged(); } } } private sealed record FilteredChangedSubscription(PrioritySetChangeKind ChangeKinds, EventHandler<PrioritySetChangedEventArgs> Handler); private sealed class FilteredChangedSubscriptionToken : IDisposable { private PrioritySet<T>? _owner; private readonly FilteredChangedSubscription _subscription; public FilteredChangedSubscriptionToken(PrioritySet<T> owner, FilteredChangedSubscription subscription) { _owner = owner; _subscription = subscription; } public void Dispose() { if (_owner != null) { _owner.RemoveFilteredSubscription(_subscription); _owner = null; } } } private sealed class EntriesReadOnlyView : IReadOnlyList<PrioritySetEntry<T>>, IEnumerable<PrioritySetEntry<T>>, IEnumerable, IReadOnlyCollection<PrioritySetEntry<T>> { private readonly PrioritySet<T> _owner; public PrioritySetEntry<T> this[int index] { get { _owner.ValidateIndex(index); Entry<T> entry = _owner._entries[index]; return new PrioritySetEntry<T>(entry.Value, entry.Priority, index); } } public int Count => _owner.Count; public EntriesReadOnlyView(PrioritySet<T> owner) { _owner = owner; } public IEnumerator<PrioritySetEntry<T>> GetEnumerator() { for (int i = 0; i < _owner.Count; i++) { yield return this[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private sealed class ItemsReadOnlyView : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T> { private readonly PrioritySet<T> _owner; public T this[int index] => _owner[index]; public int Count => _owner.Count; public ItemsReadOnlyView(PrioritySet<T> owner) { _owner = owner; } public IEnumerator<T> GetEnumerator() { return _owner.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private readonly List<FilteredChangedSubscription> _filteredChangedSubscriptions = new List<FilteredChangedSubscription>(); private int _changedScopeDepth; private PrioritySetChangeKind _pendingChangeKind; private int? _pendingIndex; private object? _pendingValue; private int? _pendingPriority; private readonly List<Entry<T>> _entries = new List<Entry<T>>(); private readonly Dictionary<T, int> _indexByValue; private readonly Dictionary<int, T> _priorityToValue = new Dictionary<int, T>(); private readonly IEqualityComparer<T> _comparer; private readonly EntriesReadOnlyView _entriesView; private readonly ItemsReadOnlyView _itemsView; public ConflictResolution DefaultConflictResolution { get; set; } public DuplicateValuePolicy DefaultDuplicateValuePolicy { get; set; } = DuplicateValuePolicy.Reject; public PlacementIndexBias DefaultPlacementIndexBias { get; set; } public int Count => _entries.Count; public bool IsReadOnly => false; public IReadOnlyList<PrioritySetEntry<T>> Entries => _entriesView; public IReadOnlyList<T> Items => _itemsView; public T this[int index] { get { ValidateIndex(index); return _entries[index].Value; } set { ValidateIndex(index); T value2 = _entries[index].Value; if (!_comparer.Equals(value2, value)) { TrySetValueAt(index, value); } } } public event EventHandler<PrioritySetChangedEventArgs>? Changed; private void NotifyChanged(PrioritySetChangeKind changeKind, int? index = null, object? value = null, int? priority = null) { if (changeKind != PrioritySetChangeKind.None) { if (_changedScopeDepth > 0) { _pendingChangeKind |= changeKind; _pendingIndex = index; _pendingValue = value; _pendingPriority = priority; } else { RaiseChanged(new PrioritySetChangedEventArgs(changeKind, index, value, priority)); } } } private IDisposable BeginChangedScope() { _changedScopeDepth++; return new ChangedScope(this); } private void FlushPendingChanged() { if (_pendingChangeKind != PrioritySetChangeKind.None) { RaiseChanged(new PrioritySetChangedEventArgs(_pendingChangeKind, _pendingIndex, _pendingValue, _pendingPriority)); _pendingChangeKind = PrioritySetChangeKind.None; _pendingIndex = null; _pendingValue = null; _pendingPriority = null; } } public IDisposable Subscribe(PrioritySetChangeKind changeKinds, EventHandler<PrioritySetChangedEventArgs> handler) { ArgumentNullException.ThrowIfNull(handler, "handler"); if (changeKinds == PrioritySetChangeKind.None) { throw new ArgumentException("At least one change kind must be specified.", "changeKinds"); } FilteredChangedSubscription filteredChangedSubscription = new FilteredChangedSubscription(changeKinds, handler); _filteredChangedSubscriptions.Add(filteredChangedSubscription); return new FilteredChangedSubscriptionToken(this, filteredChangedSubscription); } private void RaiseChanged(PrioritySetChangedEventArgs args) { this.Changed?.Invoke(this, args); if (_filteredChangedSubscriptions.Count == 0) { return; } FilteredChangedSubscription[] array = _filteredChangedSubscriptions.ToArray(); foreach (FilteredChangedSubscription filteredChangedSubscription in array) { if ((args.ChangeKind & filteredChangedSubscription.ChangeKinds) != PrioritySetChangeKind.None) { filteredChangedSubscription.Handler(this, args); } } } private void RemoveFilteredSubscription(FilteredChangedSubscription subscription) { _filteredChangedSubscriptions.Remove(subscription); } public int Clean(CleanFlags flags = CleanFlags.NullValues) { if (flags == CleanFlags.None) { return 0; } bool flag = flags.HasFlag(CleanFlags.NullValues); bool flag2 = flags.HasFlag(CleanFlags.NullPriorities); int num = 0; for (int num2 = _entries.Count - 1; num2 >= 0; num2--) { Entry<T> entry = _entries[num2]; bool num3 = flag && entry.Value == null; bool flag3 = flag2 && !entry.Priority.HasValue; if (num3 || flag3) { int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); UnregisterPriority(valueOrDefault, entry.Value); } RemoveIndexForValue(entry.Value); _entries.RemoveAt(num2); num++; } } if (num > 0) { RebuildIndexMap(); RebuildPriorityMapFromEntries(); EnsurePriorityOrdering(); NotifyChanged(PrioritySetChangeKind.Clean); } return num; } public PrioritySet() : this((IEqualityComparer<T>?)null) { } public PrioritySet(IEnumerable<T> collection) : this(collection, (IEqualityComparer<T>?)null, DuplicateValuePolicy.Reject) { } public PrioritySet(IEnumerable<T> collection, IEqualityComparer<T>? comparer, DuplicateValuePolicy duplicateValuePolicy = DuplicateValuePolicy.Reject) : this(comparer) { ArgumentNullException.ThrowIfNull(collection, "collection"); DefaultDuplicateValuePolicy = duplicateValuePolicy; foreach (T item in collection) { if (item != null && _indexByValue.ContainsKey(item)) { switch (duplicateValuePolicy) { case DuplicateValuePolicy.ThrowOnDuplicate: throw new InvalidOperationException("Duplicate non-null value in collection."); case DuplicateValuePolicy.ReplaceExisting: Remove(item); break; case DuplicateValuePolicy.Reject: continue; } } Add(item); } } public PrioritySet(IEqualityComparer<T>? comparer) { _comparer = comparer ?? EqualityComparer<T>.Default; _indexByValue = new Dictionary<T, int>(_comparer); _entriesView = new EntriesReadOnlyView(this); _itemsView = new ItemsReadOnlyView(this); } public void Clear() { _entries.Clear(); _indexByValue.Clear(); _priorityToValue.Clear(); NotifyChanged(PrioritySetChangeKind.Clear); } public bool Contains([AllowNull] T value) { if (value == null) { return IndexOfNullReference() >= 0; } return _indexByValue.ContainsKey(value); } public void CopyTo(T[] array, int arrayIndex) { ArgumentNullException.ThrowIfNull(array, "array"); if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex"); } if (array.Length - arrayIndex < Count) { throw new ArgumentException("Destination array is not long enough."); } for (int i = 0; i < Count; i++) { array[arrayIndex + i] = _entries[i].Value; } } public IEnumerator<T> GetEnumerator() { for (int i = 0; i < _entries.Count; i++) { yield return _entries[i].Value; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public int IndexOf([AllowNull] T value) { if (value == null) { return IndexOfNullReference(); } if (!_indexByValue.TryGetValue(value, out var value2)) { return -1; } return value2; } public int? GetPriority([AllowNull] T value) { if (!TryGetIndexForLookup(value, out var index)) { return null; } return _entries[index].Priority; } public PrioritySetEntry<T>? GetEntryByValue([AllowNull] T value) { if (!TryGetIndexForLookup(value, out var index)) { return null; } Entry<T> entry = _entries[index]; return new PrioritySetEntry<T>(entry.Value, entry.Priority, index); } public T? GetByPriority(int priority) { if (!_priorityToValue.TryGetValue(priority, out var value)) { return default(T); } return value; } public bool TryGetByPriority(int priority, out T? value) { if (_priorityToValue.TryGetValue(priority, out var value2)) { value = value2; return true; } value = default(T); return false; } public PrioritySetEntry<T>? GetEntryByPriority(int priority) { if (!_priorityToValue.TryGetValue(priority, out var value)) { return null; } if (value != null && _indexByValue.TryGetValue(value, out var value2)) { return new PrioritySetEntry<T>(_entries[value2].Value, priority, value2); } for (int i = 0; i < _entries.Count; i++) { int? priority2 = _entries[i].Priority; if (priority2.HasValue) { int valueOrDefault = priority2.GetValueOrDefault(); if (valueOrDefault == priority) { return new PrioritySetEntry<T>(_entries[i].Value, priority, i); } } } return null; } public IEnumerable<T> ByPriority() { for (int i = 0; i < _entries.Count; i++) { if (_entries[i].Priority.HasValue) { yield return _entries[i].Value; } } } public void Validate() { int num = 0; for (int i = 0; i < _entries.Count; i++) { if (_entries[i].Value != null) { num++; } } if (num != _indexByValue.Count) { throw new InvalidOperationException("Non-null entry count does not match value map."); } _priorityToValue.Clear(); RebuildPriorityMapFromEntries(); for (int j = 0; j < _entries.Count; j++) { T value = _entries[j].Value; if (value != null) { if (!_indexByValue.TryGetValue(value, out var value2) || value2 != j) { throw new InvalidOperationException("Value map index mismatch."); } int? priority = _entries[j].Priority; if (priority.HasValue && PrioritySetInvariant.HasConflict(_entries, j, priority)) { throw new InvalidOperationException($"Ordering conflict at index {j}."); } } } } private ConflictResolution ResolvePolicy(ConflictResolution? resolution) { return resolution ?? DefaultConflictResolution; } private DuplicateValuePolicy ResolveDuplicatePolicy(DuplicateValuePolicy? policy) { return policy ?? DefaultDuplicateValuePolicy; } private PlacementIndexBias ResolvePlacementIndexBias(PlacementIndexBias? placementIndexBias) { return placementIndexBias ?? DefaultPlacementIndexBias; } private PlacementIndexBias ResolveEnqueuePlacementIndexBias(PlacementIndexBias? placementIndexBias) { return placementIndexBias ?? PlacementIndexBias.LowestValidIndex; } private void ValidateIndex(int index) { if ((uint)index >= (uint)_entries.Count) { throw new ArgumentOutOfRangeException("index"); } } private void RebuildIndexMap() { _indexByValue.Clear(); for (int i = 0; i < _entries.Count; i++) { T value = _entries[i].Value; if (value != null) { _indexByValue[value] = i; } } } private int IndexOfNullReference() { for (int i = 0; i < _entries.Count; i++) { if (_entries[i].Value == null) { return i; } } return -1; } private bool TryGetIndexForLookup([AllowNull] T value, out int index) { if (value == null) { index = IndexOfNullReference(); return index >= 0; } return _indexByValue.TryGetValue(value, out index); } private bool TryGetIndexForPriority(int priority, out int index) { index = -1; if (!_priorityToValue.TryGetValue(priority, out var value)) { return false; } if (value != null && _indexByValue.TryGetValue(value, out var value2)) { index = value2; return true; } for (int i = 0; i < _entries.Count; i++) { int? priority2 = _entries[i].Priority; if (priority2.HasValue) { int valueOrDefault = priority2.GetValueOrDefault(); if (valueOrDefault == priority) { index = i; return true; } } } return false; } private bool TryResolveSlotIndex(int? index, int? priority, [AllowNull] T value, bool byValue, out int resolvedIndex) { resolvedIndex = -1; if (byValue) { if (index.HasValue || priority.HasValue) { throw new ArgumentException("Specify only one slot locator (value)."); } return TryGetIndexForLookup(value, out resolvedIndex); } if (index.HasValue) { int valueOrDefault = index.GetValueOrDefault(); if (priority.HasValue) { throw new ArgumentException("Specify only one slot locator (index or priority)."); } if ((uint)valueOrDefault >= (uint)_entries.Count) { return false; } resolvedIndex = valueOrDefault; return true; } if (priority.HasValue) { int valueOrDefault2 = priority.GetValueOrDefault(); return TryGetIndexForPriority(valueOrDefault2, out resolvedIndex); } throw new ArgumentException("Specify one slot locator: index, priority, or value."); } private static int ComputeRelativeInsertIndex(int anchorIndex, bool insertAfter) { if (!insertAfter) { return anchorIndex; } return anchorIndex + 1; } private bool IsAlreadyInSet([AllowNull] T value) { if (value != null) { return _indexByValue.ContainsKey(value); } return false; } private void SetIndexForValue([AllowNull] T value, int index) { if (value != null) { _indexByValue[value] = index; } } private void RemoveIndexForValue([AllowNull] T value) { if (value != null) { _indexByValue.Remove(value); } } private bool ContainsValueIn(IEnumerable<T> values, [AllowNull] T value) { foreach (T value2 in values) { if (_comparer.Equals(value2, value)) { return true; } } return false; } private void RebuildPriorityMapFromEntries() { _priorityToValue.Clear(); for (int i = 0; i < _entries.Count; i++) { int? priority = _entries[i].Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); _priorityToValue[valueOrDefault] = _entries[i].Value; } } } private void RegisterPriority(int priority, [AllowNull] T value) { if (_priorityToValue.TryGetValue(priority, out var value2) && !_comparer.Equals(value2, value)) { throw new InvalidOperationException($"Duplicate priority {priority}."); } _priorityToValue[priority] = value; } private void UnregisterPriority(int? priority, [AllowNull] T value) { if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); if (_priorityToValue.TryGetValue(valueOrDefault, out var value2) && _comparer.Equals(value2, value)) { _priorityToValue.Remove(valueOrDefault); } } } private void UpdateEntryPriority(Entry<T> entry, int? newPriority) { UnregisterPriority(entry.Priority, entry.Value); entry.Priority = newPriority; if (newPriority.HasValue) { int valueOrDefault = newPriority.GetValueOrDefault(); RegisterPriority(valueOrDefault, entry.Value); } } public T[] ToArray() { T[] array = new T[_entries.Count]; for (int i = 0; i < _entries.Count; i++) { array[i] = _entries[i].Value; } return array; } public List<T> ToList() { List<T> list = new List<T>(_entries.Count); for (int i = 0; i < _entries.Count; i++) { list.Add(_entries[i].Value); } return list; } public HashSet<T> ToHashSet() { HashSet<T> hashSet = new HashSet<T>(_comparer); for (int i = 0; i < _entries.Count; i++) { T value = _entries[i].Value; if (value != null) { hashSet.Add(value); } } return hashSet; } public ISet<T> ToSet() { return ToHashSet(); } public static implicit operator T[](PrioritySet<T> set) { return set.ToArray(); } public static implicit operator List<T>(PrioritySet<T> set) { return set.ToList(); } public static explicit operator HashSet<T>(PrioritySet<T> set) { return set.ToHashSet(); } public bool TryAdd([AllowNull] T value, int? index = null, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null, PlacementIndexBias? placementIndexBias = null) { bool hasValue = index.HasValue; bool hasValue2 = priority.HasValue; if (IsAlreadyInSet(value)) { if (!hasValue && !hasValue2) { return HandleDuplicateAdd(value, duplicateValuePolicy); } ApplyAddToExistingSlot(value, index, priority, resolution); int? index2 = null; int value2; if (value == null) { int num = IndexOfNullReference(); if (num >= 0) { index2 = num; } } else if (_indexByValue.TryGetValue(value, out value2)) { index2 = value2; } int? obj; if (index2.HasValue) { int valueOrDefault = index2.GetValueOrDefault(); obj = _entries[valueOrDefault].Priority; } else { obj = null; } int? priority2 = obj; PrioritySetChangeKind prioritySetChangeKind = PrioritySetChangeKind.None; if (hasValue) { prioritySetChangeKind |= PrioritySetChangeKind.Reorder; } if (hasValue2) { prioritySetChangeKind |= PrioritySetChangeKind.PriorityChange; } NotifyChanged(prioritySetChangeKind, index2, value, priority2); return true; } PrioritySetChangeKind prioritySetChangeKind2 = PrioritySetChangeKind.None; prioritySetChangeKind2 |= PrioritySetChangeKind.Add; if (hasValue) { prioritySetChangeKind2 |= PrioritySetChangeKind.Reorder; } if (hasValue2) { prioritySetChangeKind2 |= PrioritySetChangeKind.PriorityChange; } if (!hasValue && !hasValue2) { InsertCore(_entries.Count, value, null); int value3; int? index3 = ((value == null) ? new int?(IndexOfNullReference()) : (_indexByValue.TryGetValue(value, out value3) ? new int?(value3) : ((int?)null))); int? obj2; if (index3.HasValue) { int valueOrDefault2 = index3.GetValueOrDefault(); obj2 = _entries[valueOrDefault2].Priority; } else { obj2 = null; } int? priority3 = obj2; NotifyChanged(prioritySetChangeKind2, index3, value, priority3); return true; } InsertWithPlacement(value, index, priority, resolution, ResolvePlacementIndexBias(placementIndexBias)); int? index4 = null; int value4; if (value == null) { int num2 = IndexOfNullReference(); if (num2 >= 0) { index4 = num2; } } else if (_indexByValue.TryGetValue(value, out value4)) { index4 = value4; } int? obj3; if (index4.HasValue) { int valueOrDefault3 = index4.GetValueOrDefault(); obj3 = _entries[valueOrDefault3].Priority; } else { obj3 = null; } int? priority4 = obj3; NotifyChanged(prioritySetChangeKind2, index4, value, priority4); return true; } public bool Add([AllowNull] T value, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null, PlacementIndexBias? placementIndexBias = null) { return TryAdd(value, null, priority, resolution, duplicateValuePolicy, placementIndexBias); } public bool AddAt([AllowNull] T value, int index, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { return TryAdd(value, index, null, resolution, duplicateValuePolicy); } public bool AddAt([AllowNull] T value, int index, int priority, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { return TryAdd(value, index, priority, resolution, duplicateValuePolicy); } void ICollection<T>.Add(T value) { Add(value); } bool ISet<T>.Add(T value) { return Add(value); } public void Insert(int index, [AllowNull] T value) { TryInsert(index, value); } public void Insert(int index, [AllowNull] T value, int? priority, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { TryInsert(index, value, priority, resolution, duplicateValuePolicy); } public bool TryInsert(int index, [AllowNull] T value) { return TryInsert(index, value, null); } public bool TryInsert(int index, [AllowNull] T value, int? priority, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (IsAlreadyInSet(value) && !TryPrepareDuplicateForInsert(value, duplicateValuePolicy)) { return false; } if (!priority.HasValue) { InsertCore(index, value, null); int value2; int? index2 = ((value == null) ? new int?(IndexOfNullReference()) : (_indexByValue.TryGetValue(value, out value2) ? new int?(value2) : ((int?)null))); int? obj; if (index2.HasValue) { int valueOrDefault = index2.GetValueOrDefault(); obj = _entries[valueOrDefault].Priority; } else { obj = null; } int? priority2 = obj; NotifyChanged(PrioritySetChangeKind.Add, index2, value, priority2); return true; } InsertWithPlacement(value, index, priority, resolution, ResolvePlacementIndexBias(null)); SyncPriorityMap(); int? index3 = null; int value3; if (value == null) { int num = IndexOfNullReference(); if (num >= 0) { index3 = num; } } else if (_indexByValue.TryGetValue(value, out value3)) { index3 = value3; } int? obj2; if (index3.HasValue) { int valueOrDefault2 = index3.GetValueOrDefault(); obj2 = _entries[valueOrDefault2].Priority; } else { obj2 = null; } int? priority3 = obj2; PrioritySetChangeKind prioritySetChangeKind = PrioritySetChangeKind.Add; if (priority.HasValue) { prioritySetChangeKind |= PrioritySetChangeKind.PriorityChange; } NotifyChanged(prioritySetChangeKind, index3, value, priority3); return true; } void IList<T>.Insert(int index, T item) { Insert(index, item); } public void InsertRelativeAt([AllowNull] T value, int anchorIndex, bool insertAfter = true, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { TryInsertRelativeAt(value, anchorIndex, insertAfter, priority, resolution, duplicateValuePolicy); } public void InsertRelativeByPriority([AllowNull] T value, int anchorPriority, bool insertAfter = true, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { TryInsertRelativeByPriority(value, anchorPriority, insertAfter, priority, resolution, duplicateValuePolicy); } public void InsertRelative([AllowNull] T value, [AllowNull] T anchorValue, bool insertAfter = true, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { TryInsertRelative(value, anchorValue, insertAfter, priority, resolution, duplicateValuePolicy); } public bool TryInsertRelativeAt([AllowNull] T value, int anchorIndex, bool insertAfter = true, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (!TryResolveSlotIndex(anchorIndex, null, default(T), byValue: false, out var resolvedIndex)) { return false; } int index = ComputeRelativeInsertIndex(resolvedIndex, insertAfter); return TryInsert(index, value, priority, resolution, duplicateValuePolicy); } public bool TryInsertRelativeByPriority([AllowNull] T value, int anchorPriority, bool insertAfter = true, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (!TryResolveSlotIndex(null, anchorPriority, default(T), byValue: false, out var resolvedIndex)) { return false; } int index = ComputeRelativeInsertIndex(resolvedIndex, insertAfter); return TryInsert(index, value, priority, resolution, duplicateValuePolicy); } public bool TryInsertRelative([AllowNull] T value, [AllowNull] T anchorValue, bool insertAfter = true, int? priority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (!TryResolveSlotIndex(null, null, anchorValue, byValue: true, out var resolvedIndex)) { return false; } int index = ComputeRelativeInsertIndex(resolvedIndex, insertAfter); return TryInsert(index, value, priority, resolution, duplicateValuePolicy); } public bool Remove([AllowNull] T value) { if (!TryGetIndexForLookup(value, out var index)) { return false; } RemoveAt(index); return true; } public bool TryRemoveAt(int index) { if (index < 0 || index >= _entries.Count) { return false; } Entry<T> entry = _entries[index]; UnregisterPriority(entry.Priority, entry.Value); _entries.RemoveAt(index); RemoveIndexForValue(entry.Value); RebuildIndexMap(); EnsurePriorityOrdering(); NotifyChanged(PrioritySetChangeKind.Remove, index, entry.Value, entry.Priority); return true; } public void RemoveAt(int index) { if (!TryRemoveAt(index)) { throw new ArgumentOutOfRangeException("index"); } } public bool RemoveByPriority(int priority) { return TryRemoveByPriority(priority); } public bool TryRemoveByPriority(int priority) { if (!TryResolveSlotIndex(null, priority, default(T), byValue: false, out var resolvedIndex)) { return false; } return TryRemoveAt(resolvedIndex); } public void SetPriority([AllowNull] T value, int newPriority, ConflictResolution? resolution = null) { TrySetPriority(value, newPriority, resolution); } public bool TrySetPriority([AllowNull] T value, int newPriority, ConflictResolution? resolution = null) { if (!TryGetIndexForLookup(value, out var index)) { return false; } return TrySetPriorityAt(index, newPriority, resolution); } public void SetPriorityAt(int index, int newPriority, ConflictResolution? resolution = null) { if (!TrySetPriorityAt(index, newPriority, resolution)) { throw new ArgumentOutOfRangeException("index"); } } public bool TrySetPriorityAt(int index, int newPriority, ConflictResolution? resolution = null) { if ((uint)index >= (uint)_entries.Count) { return false; } T value = _entries[index].Value; SetPriorityAtCore(index, newPriority, resolution); int? index2 = null; int value2; if (value == null) { int num = IndexOfNullReference(); if (num >= 0) { index2 = num; } } else if (_indexByValue.TryGetValue(value, out value2)) { index2 = value2; } int? num2; if (index2.HasValue) { int valueOrDefault = index2.GetValueOrDefault(); num2 = _entries[valueOrDefault].Priority; } else { num2 = newPriority; } int? priority = num2; NotifyChanged(PrioritySetChangeKind.PriorityChange, index2, value, priority); return true; } public void SetPriorityByPriority(int currentPriority, int newPriority, ConflictResolution? resolution = null) { TrySetPriorityByPriority(currentPriority, newPriority, resolution); } public bool TrySetPriorityByPriority(int currentPriority, int newPriority, ConflictResolution? resolution = null) { if (!_priorityToValue.TryGetValue(currentPriority, out var value)) { return false; } return TrySetPriority(value, newPriority, resolution); } public void ClearPriority([AllowNull] T value) { TryClearPriority(value); } public bool TryClearPriority([AllowNull] T value) { if (!TryGetIndexForLookup(value, out var index)) { return false; } return TryClearPriorityAt(index); } public void ClearPriorityAt(int index) { ValidateIndex(index); TryClearPriorityAt(index); } public bool TryClearPriorityAt(int index) { if ((uint)index >= (uint)_entries.Count) { return false; } Entry<T> entry = _entries[index]; if (!entry.Priority.HasValue) { return false; } UpdateEntryPriority(entry, null); NotifyChanged(PrioritySetChangeKind.PriorityChange, index, entry.Value); return true; } public void ClearPriorityByPriority(int priority) { TryClearPriorityByPriority(priority); } public bool TryClearPriorityByPriority(int priority) { if (!TryResolveSlotIndex(null, priority, default(T), byValue: false, out var resolvedIndex)) { return false; } return TryClearPriorityAt(resolvedIndex); } public int ReplaceValuesWhere(Func<T, bool> shouldReplace, [AllowNull] T replacement, DuplicateValuePolicy? duplicateValuePolicy = null) { ArgumentNullException.ThrowIfNull(shouldReplace, "shouldReplace"); int num = 0; for (int i = 0; i < _entries.Count; i++) { T value = _entries[i].Value; if (shouldReplace(value) && !_comparer.Equals(value, replacement) && TryAssignValueAt(i, replacement, null, duplicateValuePolicy)) { num++; } } if (num > 0) { NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } return num; } public void SetValueAt(int index, [AllowNull] T value, DuplicateValuePolicy? duplicateValuePolicy = null, ConflictResolution? resolution = null) { TrySetValueAt(index, value, duplicateValuePolicy, resolution); } public bool TrySetValueAt(int index, [AllowNull] T value, DuplicateValuePolicy? duplicateValuePolicy = null, ConflictResolution? resolution = null) { ValidateIndex(index); T value2 = _entries[index].Value; if (_comparer.Equals(value2, value)) { return true; } if (!TryAssignValueAt(index, value, resolution, duplicateValuePolicy)) { return false; } int? index2; if (value != null) { index2 = ((!_indexByValue.TryGetValue(value, out var value3)) ? ((int?)null) : new int?(value3)); } else { int num = IndexOfNullReference(); index2 = ((num >= 0) ? new int?(num) : ((int?)null)); } int? obj; if (index2.HasValue) { int valueOrDefault = index2.GetValueOrDefault(); obj = _entries[valueOrDefault].Priority; } else { obj = null; } int? priority = obj; NotifyChanged(PrioritySetChangeKind.Update, index2, value, priority); return true; } public void SetValueByPriority(int priority, [AllowNull] T value, DuplicateValuePolicy? duplicateValuePolicy = null, ConflictResolution? resolution = null) { TrySetValueByPriority(priority, value, duplicateValuePolicy, resolution); } public bool TrySetValueByPriority(int priority, [AllowNull] T value, DuplicateValuePolicy? duplicateValuePolicy = null, ConflictResolution? resolution = null) { if (!TryGetIndexForPriority(priority, out var index)) { return false; } return TrySetValueAt(index, value, duplicateValuePolicy, resolution); } private void ReplaceEntryValueAt(int index, [AllowNull] T newValue) { ValidateIndex(index); Entry<T> entry = _entries[index]; T value = entry.Value; if (!_comparer.Equals(value, newValue)) { RemoveIndexForValue(value); int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); UnregisterPriority(valueOrDefault, value); } entry.Value = newValue; SetIndexForValue(newValue, index); priority = entry.Priority; if (priority.HasValue) { int valueOrDefault2 = priority.GetValueOrDefault(); RegisterPriority(valueOrDefault2, newValue); } } } private bool TryAssignValueAt(int index, [AllowNull] T value, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { ValidateIndex(index); if (value != null && _indexByValue.TryGetValue(value, out var value2) && value2 != index) { switch (ResolveDuplicatePolicy(duplicateValuePolicy)) { case DuplicateValuePolicy.ThrowOnDuplicate: throw new InvalidOperationException("Value already exists at another index."); case DuplicateValuePolicy.Reject: return false; case DuplicateValuePolicy.ReplaceExisting: { int? priority = _entries[value2].Priority; RemoveAt(value2); if (value2 < index) { index--; } if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); PlaceAt(index, value, valueOrDefault, ResolvePolicy(resolution)); } else { InsertCore(index, value, null); ResolvePlacement(index, indexSpecified: true, prioritySpecified: false, ResolvePolicy(resolution)); } SyncPriorityMap(); return true; } } } if (_comparer.Equals(_entries[index].Value, value)) { return true; } ReplaceEntryValueAt(index, value); if (_entries[index].Priority.HasValue) { ResolvePlacement(index, indexSpecified: true, prioritySpecified: true, ResolvePolicy(resolution)); } SyncPriorityMap(); return true; } private bool HandleDuplicateAdd([AllowNull] T value, DuplicateValuePolicy? duplicateValuePolicy) { switch (ResolveDuplicatePolicy(duplicateValuePolicy)) { case DuplicateValuePolicy.ThrowOnDuplicate: throw new InvalidOperationException("Value already exists in the set."); case DuplicateValuePolicy.Reject: return false; case DuplicateValuePolicy.ReplaceExisting: { Remove(value); InsertCore(_entries.Count, value, null); int value2; int? index = ((value == null) ? new int?(IndexOfNullReference()) : (_indexByValue.TryGetValue(value, out value2) ? new int?(value2) : ((int?)null))); int? obj; if (index.HasValue) { int valueOrDefault = index.GetValueOrDefault(); obj = _entries[valueOrDefault].Priority; } else { obj = null; } int? priority = obj; NotifyChanged(PrioritySetChangeKind.Add, index, value, priority); return true; } default: return false; } } private bool TryPrepareDuplicateForInsert([AllowNull] T value, DuplicateValuePolicy? duplicateValuePolicy) { switch (ResolveDuplicatePolicy(duplicateValuePolicy)) { case DuplicateValuePolicy.ThrowOnDuplicate: throw new InvalidOperationException("Value already exists in the set."); case DuplicateValuePolicy.Reject: return false; case DuplicateValuePolicy.ReplaceExisting: Remove(value); return true; default: return false; } } private void SetPriorityAtCore(int index, int newPriority, ConflictResolution? resolution) { Entry<T> entry = _entries[index]; if (entry.Priority == newPriority && !PrioritySetInvariant.HasConflict(_entries, index, newPriority)) { return; } int? priority = entry.Priority; UnregisterPriority(entry.Priority, entry.Value); entry.Priority = newPriority; if (!PrioritySetInvariant.HasConflict(_entries, index, newPriority)) { RegisterPriority(newPriority, entry.Value); return; } ConflictResolution conflictResolution = ResolvePolicy(resolution); if (conflictResolution == ConflictResolution.ThrowOnConflict) { entry.Priority = priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); RegisterPriority(valueOrDefault, entry.Value); } throw new InvalidOperationException("Priority conflict."); } ResolvePlacement(index, indexSpecified: false, prioritySpecified: true, conflictResolution); SyncPriorityMap(); } private void InsertWithPlacement([AllowNull] T value, int? index, int? priority, ConflictResolution? resolution, PlacementIndexBias placementIndexBias) { ConflictResolution policy = ResolvePolicy(resolution); bool hasValue = index.HasValue; bool hasValue2 = priority.HasValue; if (!hasValue && hasValue2) { int value2 = priority.Value; int index2 = ResolveTargetIndexForPriorityOnly(value, value2, null, placementIndexBias); InsertCore(index2, value, value2, syncPriorityMap: false); ResolvePlacement(index2, indexSpecified: false, prioritySpecified: true, policy); SyncPriorityMap(); } else if (hasValue && !hasValue2) { int value3 = index.Value; value3 = Math.Clamp(value3, 0, _entries.Count); InsertCore(value3, value, null); ResolvePlacement(value3, indexSpecified: true, prioritySpecified: false, policy); SyncPriorityMap(); } else if (hasValue && hasValue2) { int index3 = Math.Clamp(index.Value, 0, _entries.Count); int value4 = priority.Value; if (!PrioritySetInvariant.TryFindHighestValidIndex(_entries, value4, value, out var _)) { ShiftPrioritiesAtOrAbove(value4); } PlaceAt(index3, value, value4, policy); } else { InsertCore(_entries.Count, value, null); } } private void PlaceAt(int index, [AllowNull] T value, int priority, ConflictResolution policy) { if (IsAlreadyInSet(value)) { throw new InvalidOperationException("Value already exists in the set."); } InsertCore(index, value, priority, syncPriorityMap: false); if (policy == ConflictResolution.ThrowOnConflict && PrioritySetInvariant.HasConflict(_entries, index, priority)) { RemoveAt(index); throw new InvalidOperationException("Index and priority conflict."); } ResolvePlacement(index, indexSpecified: true, prioritySpecified: true, policy); SyncPriorityMap(); } private void ResolvePlacement(int index, bool indexSpecified, bool prioritySpecified, ConflictResolution policy) { ValidateIndex(index); Entry<T> entry = _entries[index]; T value = entry.Value; int? priority = entry.Priority; if (!priority.HasValue || !PrioritySetInvariant.HasConflict(_entries, index, priority)) { return; } if (indexSpecified && prioritySpecified) { switch (policy) { case ConflictResolution.ThrowOnConflict: throw new InvalidOperationException("Index and priority conflict."); case ConflictResolution.KeepIndex: ApplyPriorityAtIndex(index, priority, value, allowMoveFallback: true); return; case ConflictResolution.KeepPriority: if (!TryMoveToClosestValidIndex(index, priority.Value, value, policy)) { ApplyPriorityAtIndex(index, priority, value, allowMoveFallback: false); } return; } } if (indexSpecified) { ApplyPriorityAtIndex(index, priority, value, allowMoveFallback: true); } else if (prioritySpecified && !TryMoveToClosestValidIndex(index, priority.Value, value, policy)) { ApplyPriorityAtIndex(index, priority, value, allowMoveFallback: false); } } private void ApplyPriorityAtIndex(int index, int? priority, T value, bool allowMoveFallback) { try { _entries[index].Priority = PrioritySetInvariant.FindPriorityForIndex(_entries, index, priority); } catch (InvalidOperationException) when (allowMoveFallback) { int? num = priority ?? _entries[index].Priority; if (num.HasValue) { int valueOrDefault = num.GetValueOrDefault(); if (TryMoveToClosestValidIndex(index, valueOrDefault, value, ConflictResolution.KeepPriority)) { return; } } UpdateEntryPriority(_entries[index], null); } } private bool TryMoveToClosestValidIndex(int index, int priority, T value, ConflictResolution policy) { if (policy == ConflictResolution.KeepIndex) { return false; } try { int num = PrioritySetInvariant.FindClosestValidIndex(_entries, index, priority, value, index); if (num != index) { MoveEntry(index, num); } return true; } catch (InvalidOperationException) { return false; } } private Entry<T> InsertCore(int index, [AllowNull] T value, int? priority, bool syncPriorityMap = true) { index = Math.Clamp(index, 0, _entries.Count); Entry<T> entry = new Entry<T>(value, priority); _entries.Insert(index, entry); RebuildIndexMap(); if (syncPriorityMap && priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); RegisterPriority(valueOrDefault, value); } return entry; } private void SyncPriorityMap() { RebuildPriorityMapFromEntries(); } private int ResolveTargetIndexForPriorityOnly([AllowNull] T value, int priority, int? requestedIndex, PlacementIndexBias placementIndexBias) { if (requestedIndex.HasValue) { int valueOrDefault = requestedIndex.GetValueOrDefault(); valueOrDefault = Math.Clamp(valueOrDefault, 0, _entries.Count); if (!PrioritySetInvariant.TryFindHighestValidIndex(_entries, priority, value, out var _)) { ShiftPrioritiesAtOrAbove(priority); } return valueOrDefault; } if (placementIndexBias == PlacementIndexBias.LowestValidIndex) { if (PrioritySetInvariant.TryFindLowestValidIndex(_entries, priority, value, out var index2)) { return index2; } ShiftPrioritiesAtOrAbove(priority); if (PrioritySetInvariant.TryFindLowestValidIndex(_entries, priority, value, out index2)) { return index2; } return _entries.Count; } if (PrioritySetInvariant.TryFindHighestValidIndex(_entries, priority, value, out var index3)) { return index3; } ShiftPrioritiesAtOrAbove(priority); if (PrioritySetInvariant.TryFindHighestValidIndex(_entries, priority, value, out index3)) { return index3; } return _entries.Count; } private void ShiftPrioritiesAtOrAbove(int threshold) { List<Entry<T>> list = new List<Entry<T>>(); foreach (Entry<T> entry in _entries) { int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); if (valueOrDefault >= threshold) { list.Add(entry); } } } list.Sort((Entry<T> a, Entry<T> b) => b.Priority.Value.CompareTo(a.Priority.Value)); foreach (Entry<T> item in list) { int value = item.Priority.Value; if (value == int.MaxValue) { throw new InvalidOperationException("Cannot shift priority at int.MaxValue."); } UnregisterPriority(value, item.Value); int num = value + 1; item.Priority = num; RegisterPriority(num, item.Value); } } private void ApplyAddToExistingSlot([AllowNull] T value, int? index, int? priority, ConflictResolution? resolution) { if (!TryGetIndexForLookup(value, out var index2)) { return; } if (index.HasValue) { int valueOrDefault = index.GetValueOrDefault(); valueOrDefault = Math.Clamp(valueOrDefault, 0, _entries.Count - 1); if (valueOrDefault != index2) { MoveEntry(index2, valueOrDefault); index2 = valueOrDefault; } } if (priority.HasValue) { int valueOrDefault2 = priority.GetValueOrDefault(); if (_priorityToValue.TryGetValue(valueOrDefault2, out var value2) && !_comparer.Equals(value2, value)) { ShiftPrioritiesAtOrAbove(valueOrDefault2); } SetPriorityAtCore(index2, valueOrDefault2, resolution); } RepairOrderingAfterIndexChange(resolution); } public void Enqueue([AllowNull] T value) { TryEnqueue(value); } public void Enqueue([AllowNull] T value, int priority, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null, PlacementIndexBias? placementIndexBias = null) { TryEnqueue(value, priority, resolution, duplicateValuePolicy, placementIndexBias); } public bool TryEnqueue([AllowNull] T value) { return Add(value); } public bool TryEnqueue([AllowNull] T value, int priority, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null, PlacementIndexBias? placementIndexBias = null) { try { return Add(value, priority, resolution, duplicateValuePolicy, ResolveEnqueuePlacementIndexBias(placementIndexBias)); } catch (InvalidOperationException) { return false; } } public T Dequeue() { if (!TryDequeue(out var result)) { throw new InvalidOperationException("The set is empty."); } return result; } public bool TryDequeue(out T result) { if (_entries.Count == 0) { result = default(T); return false; } T value = _entries[0].Value; RemoveAt(0); result = value; return true; } public T Peek() { if (!TryPeek(out var result)) { throw new InvalidOperationException("The set is empty."); } return result; } public bool TryPeek(out T result) { if (_entries.Count == 0) { result = default(T); return false; } result = _entries[0].Value; return true; } public IEnumerable<T> ByPriorityRange(int minInclusive, int maxInclusive) { for (int i = 0; i < _entries.Count; i++) { int? priority = _entries[i].Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); if (valueOrDefault >= minInclusive && valueOrDefault <= maxInclusive) { yield return _entries[i].Value; } } } } public IEnumerable<PrioritySetEntry<T>> EntriesByPriorityRange(int minInclusive, int maxInclusive) { for (int i = 0; i < _entries.Count; i++) { int? priority = _entries[i].Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); if (valueOrDefault >= minInclusive && valueOrDefault <= maxInclusive) { yield return new PrioritySetEntry<T>(_entries[i].Value, valueOrDefault, i); } } } } internal void ApplyIndexPermutation(ReadOnlySpan<int> newOrder) { if (newOrder.Length != _entries.Count) { throw new ArgumentException("Permutation length must match Count.", "newOrder"); } bool[] array = new bool[_entries.Count]; ReadOnlySpan<int> readOnlySpan = newOrder; for (int i = 0; i < readOnlySpan.Length; i++) { int num = readOnlySpan[i]; if ((uint)num >= (uint)_entries.Count) { throw new ArgumentOutOfRangeException("newOrder"); } if (array[num]) { throw new ArgumentException("Permutation must be unique.", "newOrder"); } array[num] = true; } Entry<T>[] array2 = new Entry<T>[_entries.Count]; for (int j = 0; j < newOrder.Length; j++) { array2[j] = _entries[newOrder[j]]; } for (int k = 0; k < array2.Length; k++) { _entries[k] = array2[k]; } RebuildIndexMap(); RebuildPriorityMapFromEntries(); } internal void RepairOrderingAfterIndexChange(ConflictResolution? resolution = null) { ConflictResolution conflictResolution = ResolvePolicy(resolution); if (conflictResolution == ConflictResolution.ThrowOnConflict) { conflictResolution = ConflictResolution.KeepIndex; } int num = Math.Max(_entries.Count * 2, 1); for (int i = 0; i < num; i++) { bool flag = false; for (int j = 0; j < _entries.Count; j++) { Entry<T> entry = _entries[j]; if (!entry.Priority.HasValue || !PrioritySetInvariant.HasConflict(_entries, j, entry.Priority)) { continue; } if (conflictResolution == ConflictResolution.KeepPriority) { try { int num2 = PrioritySetInvariant.FindClosestValidIndex(_entries, j, entry.Priority.Value, entry.Value, j); if (num2 != j) { MoveEntry(j, num2); flag = true; break; } } catch (InvalidOperationException) { } } try { int num3 = PrioritySetInvariant.FindPriorityForIndex(_entries, j, entry.Priority); if (num3 != entry.Priority) { UpdateEntryPriority(entry, num3); flag = true; continue; } } catch (InvalidOperationException) { RepairPrioritiesAfterSort(); return; } if (PrioritySetInvariant.HasConflict(_entries, j, entry.Priority) && conflictResolution != ConflictResolution.KeepIndex && TryMoveToClosestValidIndex(j, entry.Priority.Value, entry.Value, conflictResolution)) { flag = true; break; } } if (!flag) { break; } } for (int k = 0; k < _entries.Count; k++) { Entry<T> entry2 = _entries[k]; if (entry2.Priority.HasValue && PrioritySetInvariant.HasConflict(_entries, k, entry2.Priority)) { RepairPrioritiesAfterSort(); break; } } SyncPriorityMap(); } internal void EnsurePriorityOrdering() { for (int i = 0; i < _entries.Count; i++) { Entry<T> entry = _entries[i]; if (entry.Priority.HasValue && PrioritySetInvariant.HasConflict(_entries, i, entry.Priority)) { RepairPrioritiesAfterSort(); break; } } } internal void RepairPrioritiesAfterSort() { if (!HasAnyPriorityOrderingConflict()) { return; } List<(Entry<T>, int)> list = new List<(Entry<T>, int)>(); for (int i = 0; i < _entries.Count; i++) { Entry<T> entry = _entries[i]; int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); list.Add((entry, valueOrDefault)); UnregisterPriority(entry.Priority, entry.Value); entry.Priority = null; } } HashSet<int> hashSet = new HashSet<int>(); int? num = null; foreach (var item in list) { var (entry2, num2) = item; if (num.HasValue) { int valueOrDefault2 = num.GetValueOrDefault(); if (num2 > valueOrDefault2) { num2 = valueOrDefault2; } } while (hashSet.Contains(num2)) { if (num2 == int.MinValue) { throw new InvalidOperationException("Cannot assign unique priorities after sort."); } num2--; } UpdateEntryPriority(entry2, num2); hashSet.Add(num2); num = num2; } SyncPriorityMap(); } private bool HasAnyPriorityOrderingConflict() { for (int i = 0; i < _entries.Count; i++) { Entry<T> entry = _entries[i]; if (entry.Priority.HasValue && PrioritySetInvariant.HasConflict(_entries, i, entry.Priority)) { return true; } } return false; } private void MoveEntry(int fromIndex, int toIndex) { if (fromIndex != toIndex) { Entry<T> item = _entries[fromIndex]; _entries.RemoveAt(fromIndex); toIndex = Math.Clamp(toIndex, 0, _entries.Count); _entries.Insert(toIndex, item); RebuildIndexMap(); SyncPriorityMap(); } } public void UnionWith(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); if (other == this) { return; } using (BeginChangedScope()) { if (other is PrioritySet<T> prioritySet) { foreach (Entry<T> entry in prioritySet._entries) { if (entry.Value == null || !Contains(entry.Value)) { int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); Add(entry.Value, valueOrDefault); } else { TryAdd(entry.Value); } } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); return; } foreach (T item in other) { if (item == null || !Contains(item)) { TryAdd(item); } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } } public void UnionWith(IEnumerable<T> other, ConflictResolution? resolution) { ArgumentNullException.ThrowIfNull(other, "other"); if (other == this) { return; } using (BeginChangedScope()) { if (other is PrioritySet<T> prioritySet) { foreach (Entry<T> entry in prioritySet._entries) { if (entry.Value == null || !Contains(entry.Value)) { int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); Add(entry.Value, valueOrDefault, resolution); } else { TryAdd(entry.Value); } } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); return; } foreach (T item in other) { if (item == null || !Contains(item)) { TryAdd(item); } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } } public void IntersectWith(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); using (BeginChangedScope()) { CollectUniqueMembers(other, out HashSet<T> nonNullMembers, out bool hasNull); for (int num = Count - 1; num >= 0; num--) { T value = _entries[num].Value; if (value == null) { if (!hasNull) { RemoveAt(num); } } else if (!nonNullMembers.Contains(value)) { RemoveAt(num); } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } } public void ExceptWith(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); using (BeginChangedScope()) { if (other == this) { Clear(); NotifyChanged(PrioritySetChangeKind.BulkSetOperation); return; } foreach (T item in other) { Remove(item); } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } } public void SymmetricExceptWith(IEnumerable<T> other, ConflictResolution? resolution) { ArgumentNullException.ThrowIfNull(other, "other"); using (BeginChangedScope()) { CollectUniqueMembers(other, out HashSet<T> nonNullMembers, out bool hasNull); if (other is PrioritySet<T> prioritySet) { bool flag = false; foreach (Entry<T> entry in prioritySet._entries) { if (entry.Value == null) { flag = true; } else if (!Remove(entry.Value)) { int? priority = entry.Priority; if (priority.HasValue) { int valueOrDefault = priority.GetValueOrDefault(); Add(entry.Value, valueOrDefault, resolution); } else { TryAdd(entry.Value); } } } if (flag) { if (IndexOfNullReference() >= 0) { while (Remove(default(T))) { } } else { TryAdd(default(T)); } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); return; } foreach (T item in nonNullMembers) { if (!Remove(item)) { TryAdd(item); } } if (hasNull) { if (IndexOfNullReference() >= 0) { while (Remove(default(T))) { } } else { TryAdd(default(T)); } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } } public void SymmetricExceptWith(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); using (BeginChangedScope()) { CollectUniqueMembers(other, out HashSet<T> nonNullMembers, out bool hasNull); foreach (T item in nonNullMembers) { if (!Remove(item)) { TryAdd(item); } } if (hasNull) { if (IndexOfNullReference() >= 0) { while (Remove(default(T))) { } } else { TryAdd(default(T)); } } NotifyChanged(PrioritySetChangeKind.BulkSetOperation); } } public bool IsSubsetOf(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); CollectUniqueMembers(this, out HashSet<T> nonNullMembers, out bool hasNull); CollectUniqueMembers(other, out HashSet<T> nonNullMembers2, out bool hasNull2); foreach (T item in nonNullMembers) { if (!nonNullMembers2.Contains(item)) { return false; } } if (hasNull && !hasNull2) { return false; } return true; } public bool IsProperSubsetOf(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); CollectUniqueMembers(this, out HashSet<T> nonNullMembers, out bool hasNull); CollectUniqueMembers(other, out HashSet<T> nonNullMembers2, out bool hasNull2); int num = nonNullMembers.Count + (hasNull ? 1 : 0); int num2 = nonNullMembers2.Count + (hasNull2 ? 1 : 0); if (IsSubsetOf(other)) { return num < num2; } return false; } public bool IsSupersetOf(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); CollectUniqueMembers(other, out HashSet<T> nonNullMembers, out bool hasNull); foreach (T item in nonNullMembers) { if (!Contains(item)) { return false; } } if (hasNull && IndexOfNullReference() < 0) { return false; } return true; } public bool IsProperSupersetOf(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); CollectUniqueMembers(other, out HashSet<T> nonNullMembers, out bool hasNull); int num = nonNullMembers.Count + (hasNull ? 1 : 0); int uniqueMemberCount = GetUniqueMemberCount(); if (IsSupersetOf(other)) { return uniqueMemberCount > num; } return false; } public bool Overlaps(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); CollectUniqueMembers(this, out HashSet<T> nonNullMembers, out bool hasNull); CollectUniqueMembers(other, out HashSet<T> nonNullMembers2, out bool hasNull2); if (hasNull && hasNull2) { return true; } foreach (T item in nonNullMembers) { if (nonNullMembers2.Contains(item)) { return true; } } return false; } public bool SetEquals(IEnumerable<T> other) { ArgumentNullException.ThrowIfNull(other, "other"); CollectUniqueMembers(this, out HashSet<T> nonNullMembers, out bool hasNull); CollectUniqueMembers(other, out HashSet<T> nonNullMembers2, out bool hasNull2); if (hasNull != hasNull2) { return false; } return nonNullMembers.SetEquals(nonNullMembers2); } private int GetUniqueMemberCount() { CollectUniqueMembers(this, out HashSet<T> nonNullMembers, out bool hasNull); return nonNullMembers.Count + (hasNull ? 1 : 0); } private void CollectUniqueMembers(IEnumerable<T> source, out HashSet<T> nonNullMembers, out bool hasNull) { nonNullMembers = new HashSet<T>(_comparer); hasNull = false; foreach (T item in source) { if (item == null) { hasNull = true; } else { nonNullMembers.Add(item); } } } public PrioritySet(PrioritySet<T> source) : this(source?._comparer) { ArgumentNullException.ThrowIfNull(source, "source"); DefaultConflictResolution = source.DefaultConflictResolution; DefaultDuplicateValuePolicy = source.DefaultDuplicateValuePolicy; DefaultPlacementIndexBias = source.DefaultPlacementIndexBias; _entries.Clear(); for (int i = 0; i < source._entries.Count; i++) { Entry<T> entry = source._entries[i]; _entries.Add(new Entry<T>(entry.Value, entry.Priority)); } RebuildIndexMap(); SyncPriorityMap(); } public PrioritySetSnapshot<T> CreateSnapshot() { PrioritySetEntry<T>[] array = new PrioritySetEntry<T>[_entries.Count]; for (int i = 0; i < _entries.Count; i++) { array[i] = new PrioritySetEntry<T>(_entries[i].Value, _entries[i].Priority, i); } return new PrioritySetSnapshot<T>(array); } public PrioritySet<T> Clone() { return new PrioritySet<T>(this); } public void Sort(Comparison<T> comparison) { ArgumentNullException.ThrowIfNull(comparison, "comparison"); if (_entries.Count > 1) { int[] array = (from x in (from i in Enumerable.Range(0, _entries.Count) select (Index: i, Value: _entries[i].Value)).OrderBy(((int Index, T Value) x) => x.Value, Comparer<T>.Create(comparison)).ThenBy(((int Index, T Value) x) => x.Index) select x.Index).ToArray(); ApplyIndexPermutation(array); RepairPrioritiesAfterSort(); NotifyChanged(PrioritySetChangeKind.Sort); } } public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey>? comparer = null) { ArgumentNullException.ThrowIfNull(keySelector, "keySelector"); if (comparer == null) { comparer = Comparer<TKey>.Default; } Sort((T a, T b) => comparer.Compare(keySelector(a), keySelector(b))); } public void SetIndexAt(int index, int newIndex, ConflictResolution? resolution = null) { TrySetIndexAt(index, newIndex, resolution); } public bool TrySetIndexAt(int index, int newIndex, ConflictResolution? resolution = null) { if ((uint)index >= (uint)_entries.Count) { return false; } int num = Math.Clamp(newIndex, 0, _entries.Count - 1); if (num == index) { return true; } T value = _entries[index].Value; int? priority = _entries[index].Priority; MoveEntry(index, num); RepairOrderingAfterIndexChange(resolution); int? index2 = num; if (value != null && _indexByValue.TryGetValue(value, out var value2)) { index2 = value2; } else if (value == null) { int num2 = IndexOfNullReference(); if (num2 >= 0) { index2 = num2; } } int? num3; if (index2.HasValue) { int valueOrDefault = index2.GetValueOrDefault(); num3 = _entries[valueOrDefault].Priority; } else { num3 = priority; } int? priority2 = num3; NotifyChanged(PrioritySetChangeKind.Reorder, index2, value, priority2); return true; } public void SetIndexByValue([AllowNull] T value, int newIndex, ConflictResolution? resolution = null) { TrySetIndexByValue(value, newIndex, resolution); } public bool TrySetIndexByValue([AllowNull] T value, int newIndex, ConflictResolution? resolution = null) { if (!TryResolveSlotIndex(null, null, value, byValue: true, out var resolvedIndex)) { return false; } return TrySetIndexAt(resolvedIndex, newIndex, resolution); } public void SetIndexByPriority(int currentPriority, int newIndex, ConflictResolution? resolution = null) { TrySetIndexByPriority(currentPriority, newIndex, resolution); } public bool TrySetIndexByPriority(int currentPriority, int newIndex, ConflictResolution? resolution = null) { if (!TryResolveSlotIndex(null, currentPriority, default(T), byValue: false, out var resolvedIndex)) { return false; } return TrySetIndexAt(resolvedIndex, newIndex, resolution); } public void SetSlotAt(int index, int newIndex, int newPriority, ConflictResolution? resolution = null) { TrySetSlotAt(index, newIndex, newPriority, resolution); } public bool TrySetSlotAt(int index, int newIndex, int newPriority, ConflictResolution? resolution = null) { return TrySetSlotAtCore(index, updateValue: false, default(T), newIndex, newPriority, resolution); } public void SetSlotAt(int index, [AllowNull] T newValue, int? newIndex = null, int? newPriority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { TrySetSlotAt(index, newValue, newIndex, newPriority, resolution, duplicateValuePolicy); } public bool TrySetSlotAt(int index, [AllowNull] T newValue, int? newIndex = null, int? newPriority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (1 + (newIndex.HasValue ? 1 : 0) + (newPriority.HasValue ? 1 : 0) < 2) { throw new ArgumentException("Changing only the value requires SetValueAt/TrySetValueAt. Changing only index or priority requires TrySetIndexAt or SetPriorityAt.", "newValue"); } return TrySetSlotAtCore(index, updateValue: true, newValue, newIndex, newPriority, resolution, duplicateValuePolicy); } public bool TrySetSlotByValue([AllowNull] T currentValue, int? newIndex = null, int? newPriority = null, ConflictResolution? resolution = null) { if (!TryGetIndexForLookup(currentValue, out var index)) { return false; } if (!newIndex.HasValue && !newPriority.HasValue) { return true; } if (newIndex.HasValue) { int valueOrDefault = newIndex.GetValueOrDefault(); if (newPriority.HasValue) { int valueOrDefault2 = newPriority.GetValueOrDefault(); return TrySetSlotAt(index, valueOrDefault, valueOrDefault2, resolution); } } if (newIndex.HasValue) { int valueOrDefault3 = newIndex.GetValueOrDefault(); return TrySetIndexAt(index, valueOrDefault3, resolution); } return TrySetPriorityAt(index, newPriority.Value, resolution); } public bool TrySetSlotByValue([AllowNull] T currentValue, [AllowNull] T newValue, int? newIndex = null, int? newPriority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (!TryGetIndexForLookup(currentValue, out var index)) { return false; } if (!newIndex.HasValue && !newPriority.HasValue) { return TrySetValueAt(index, newValue, duplicateValuePolicy, resolution); } return TrySetSlotAt(index, newValue, newIndex, newPriority, resolution, duplicateValuePolicy); } public bool TrySetSlotByPriority(int currentPriority, int? newIndex = null, int? newPriority = null, ConflictResolution? resolution = null) { if (!TryGetIndexForPriority(currentPriority, out var index)) { return false; } if (!newIndex.HasValue && !newPriority.HasValue) { return true; } if (newIndex.HasValue) { int valueOrDefault = newIndex.GetValueOrDefault(); if (newPriority.HasValue) { int valueOrDefault2 = newPriority.GetValueOrDefault(); return TrySetSlotAt(index, valueOrDefault, valueOrDefault2, resolution); } } if (newIndex.HasValue) { int valueOrDefault3 = newIndex.GetValueOrDefault(); return TrySetIndexAt(index, valueOrDefault3, resolution); } return TrySetPriorityAt(index, newPriority.Value, resolution); } public bool TrySetSlotByPriority(int currentPriority, [AllowNull] T newValue, int? newIndex = null, int? newPriority = null, ConflictResolution? resolution = null, DuplicateValuePolicy? duplicateValuePolicy = null) { if (!TryGetIndexForPriority(currentPriority, out var index)) { return false; } if (!newIndex.HasValue && !newPriority.HasValue) { return TrySetValueAt(index, newValue, duplicateValuePolicy, resolution); } return TrySetSlotAt(index, newValue, newIndex, newPriority, resolution, duplicateValuePolicy); } private bool TrySetSlotAtCore(int index, bool updateValue, [AllowNull] T newValue, int? newIndex, int? newPriority, ConflictResolution? resolution, DuplicateValuePolicy? duplicateValuePolicy = null) { if ((uint)index >= (uint)_entries.Count) { return false; } if (!updateValue) { if (newIndex.HasValue) { newIndex.GetValueOrDefault(); if (newPriority.HasValue) { newPriority.GetValueOrDefault(); goto IL_009c; } } if (newIndex.HasValue) { int valueOrDefault = newIndex.GetValueOrDefault(); return TrySetIndexAt(index, valueOrDefault, resolution); } if (newPriority.HasValue) { int valueOrDefault2 = newPriority.GetValueOrDefault(); return TrySetPriorityAt(index, valueOrDefault2, resolution); } return false; } if (1 + (newIndex.HasValue ? 1 : 0) + (newPriority.HasValue ? 1 : 0) < 2) { return TrySetValueAt(index, newValue, duplicateValuePolicy, resolution); } goto IL_009c; IL_009c: T value = _entries[index].Value; T val = (T)(updateValue ? ((object)newValue) : ((object)value)); PrioritySetChangeKind prioritySetChangeKind = PrioritySetChangeKind.None; if (newIndex.HasValue) { int valueOrDefault3 = newIndex.GetValueOrDefault(); int num = Math.Clamp(valueOrDefault3, 0, _entries.Count - 1); if (num != index) { MoveEntry(index, num); index = num; prioritySetChangeKind |= PrioritySetChangeKind.Reorder; } } if (updateValue && !_comparer.Equals(_entries[index].Value, newValue)) { if (!TryAssignValueAt(index, newValue, resolution, duplicateValuePolicy)) { return false; } prioritySetChangeKind |= PrioritySetChangeKind.Update; } if (newPriority.HasValue) { int valueOrDefault4 = newPriority.GetValueOrDefault(); SetPriorityAtCore(index, valueOrDefault4, resolution); prioritySetChangeKind |= PrioritySetChangeKind.PriorityChange; } RepairOrderingAfterIndexChange(resolution); if (prioritySetChangeKind == PrioritySetChangeKind.None) { prioritySetChangeKind = PrioritySetChangeKind.Update; } int? index2 = null; if (val != null && _indexByValue.TryGetValue(val, out var value2)) { index2 = value2; } else if (val == null) { int num2 = IndexOfNullReference(); if (num2 >= 0) { index2 = num2; } } int? obj; if (index2.HasValue) { int valueOrDefault5 = index2.GetValueOrDefault(); obj = _entries[valueOrDefault5].Priority; } else { obj = null; } int? priority = obj; NotifyChanged(prioritySetChangeKind, index2, val, priority); return true; } } public sealed class PrioritySetSnapshot<T> : IReadOnlyList<PrioritySetEntry<T>>, IEnumerable<PrioritySetEntry<T>>, IEnumerable, IReadOnlyCollection<PrioritySetEntry<T>> { private readonly PrioritySetEntry<T>[] _entries; public PrioritySetEntry<T> this[int index] => _entries[index]; public int Count => _entries.Length; internal PrioritySetSnapshot(PrioritySetEntry<T>[] entries) { _entries = entries; } public IEnumerator<PrioritySetEntry<T>> GetEnumerator() { return ((IEnumerable<PrioritySetEntry<T>>)_entries).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public readonly struct PrioritySetEntry<T> { public T Value { get; } public int? Priority { get; } public int Index { get; } public PrioritySetEntry([AllowNull] T value, int? priority, int index) { Value = value; Priority = priority; Index = index; } } internal static class PrioritySetInvariant { public static int FindPreviousPrioritizedIndex<T>(IReadOnlyList<Entry<T>> entries, int index) { for (int num = index - 1; num >= 0; num--) { if (entries[num].Priority.HasValue) { return num; } } return -1; } public static int FindNextPrioritizedIndex<T>(IReadOnlyList<Entry<T>> entries, int index) { for (int i = index + 1; i < entries.Count; i++) { if (entries[i].Priority.HasValue) { return i; } } return -1; } public static bool HasDuplicatePriority<T>(IReadOnlyList<Entry<T>> entries, int index, int priority) { for (int i = 0; i < entries.Count; i++) { if (i != index && entries[i].Priority == priority) { return true; } } return false; } public static bool HasConflict<T>(IReadOnlyList<Entry<T>> entries, int index, int? priority) { if (!priority.HasValue) { return false; } int value = priority.Value; if (HasDuplicatePriority(entries, index, value)) { return true; } int num = FindPreviousPrioritizedIndex(entries, index); if (num >= 0 && entries[num].Priority.Value < value) { return true; } int num2 = FindNextPrioritizedIndex(entries, index); if (num2 >= 0 && value < entries[num2].Priority.Value) { return true; } return false; } public static bool IsValidPlacement<T>(IReadOnlyList<Entry<T>> entries, int index, int? priority) { return !HasConflict(entries, index, priority); } public static (int Min, int Max)? GetAllowedPriorityRange<T>(IReadOnlyList<Entry<T>> entries, int index) { int num = FindPreviousPrioritizedIndex(entries, index); int num2 = FindNextPrioritizedIndex(entries, index); if (num < 0 && num2 < 0) { return null; } int num3 = ((num >= 0) ? entries[num].Priority.Value : int.MaxValue); int num4 = ((num2 >= 0) ? entries[num2].Priority.Value : int.MinValue); if (num4 > num3) { return null; } return (num4, num3); } public static int FindPriorityForIndex<T>(IReadOnlyList<Entry<T>> entries, int index, int? requestedPriority) { if (requestedPriority.HasValue) { int valueOrDefault = requestedPriority.GetValueOrDefault(); if (IsValidPlacement(entries, index, valueOrDefault)) { return valueOrDefault; } } (int, int)? allowedPriorityRange = GetAllowedPriorityRange(entries, index); if (!allowedPriorityRange.HasValue) { if (requestedPriority.HasValue) { int valueOrDefault2 = requestedPriority.GetValueOrDefault(); if (!HasDuplicatePriority(entries, index, valueOrDefault2)) { return valueOrDefault2; } } for (int num = int.MaxValue; num >= int.MinValue; num--) { if (!HasDuplicatePriority(entries, index, num)) { return num; } } throw new InvalidOperationException("No valid priority exists for the requested index."); } var (num2, num3) = allowedPriorityRange.Value; if (requestedPriority.HasValue) { int valueOrDefault3 = requestedPriority.GetValueOrDefault(); int num4 = Math.Clamp(valueOrDefault3, num2, num3); if (!HasDuplicatePriority(entries, index, num4)) { return num4; } } for (int num5 = num3; num5 >= num2; num5--) { if (!HasDuplicatePriority(entries, index, num5)) { return num5; } } throw new InvalidOperationException("No valid priority exists for the requested index."); } public static int FindClosestValidIndex<T>(IReadOnlyList<Entry<T>> entries, int desiredIndex, int priority, T value, int sourceIndex = -1) { desiredIndex = Math.Clamp(desiredIndex, 0, entries.Count); int num = -1; int num2 = int.MaxValue; if (sourceIndex >= 0) { for (int i = 0; i < entries.Count; i++) { if (TrySimulateMove(entries, sourceIndex, i, priority)) { int num3 = Math.Abs(i - desiredIndex); if (num3 < num2 || (num3 == num2 && i < num)) { num2 = num3; num = i; } } } } else { for (int j = 0; j <= entries.Count; j++) { if (TrySimulatePlacement(entries, j, priority, value)) { int num4 = Math.Abs(j - desiredIndex); if (num4 < num2 || (num4 == num2 && j < num)) { num2 = num4; num = j; } } } } if (num < 0) { throw new InvalidOperationException("No valid index exists for the requested priority."); } return num; } public static bool TryFindHighestValidIndex<T>(IReadOnlyList<Entry<T>> entries, int priority, T value, out int index) { for (int num = entries.Count; num >= 0; num--) { if (TrySimulatePlacement(entries, num, priority, value)) { index = num; return true; } } index = 0; return false; } public static bool TryFindLowestValidIndex<T>(IReadOnlyList<Entry<T>> entries, int priority, T value, out int index) { for (int i = 0; i <= entries.Count; i++) { if (TrySimulatePlacement(entries, i, priority, value)) { index = i; return true; } } index = 0; return false; } private static bool TrySimulatePlacement<T>(IReadOnlyList<Entry<T>> entries, int index, int priority, T value) { List<Entry<T>> list = new List<Entry<T>>(entries); if (index > list.Count) { return false; } if (index == list.Count) { list.Add(new Entry<T>(value, priority)); } else { list.Insert(index, new Entry<T>(value, priority)); } return IsValidPlacement(list, index, priority); } private static bool TrySimulateMove<T>(IReadOnlyList<Entry<T>> entries, int fromIndex, int toIndex, int priority) { if ((uint)fromIndex >= (uint)entries.Count) { return false; } T value = entries[fromIndex].Value; List<Entry<T>> list = new List<Entry<T>>(); for (int i = 0; i < entries.Count; i++) { if (i != fromIndex) { list.Add(entries[i]); } } int index = Math.Clamp(toIndex, 0, list.Count); list.Insert(index, new Entry<T>(value, priority)); return IsValidPlacement(list, index, priority); } } internal sealed class Entry<T> { public T Value { get; [param: AllowNull] set; } public int? Priority { get; set; } public Entry([AllowNull] T value, int? priority) { Value = value; Priority = priority; } } }
Patchers/Il2CppInteropFix.Patcher.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Preloader.Core.Patching; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Runtime; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("Il2CppInteropFix.Patcher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+2f15411dcb5b83d69331116c439ca50c214c1902")] [assembly: AssemblyProduct("Il2CppInteropFix.Patcher")] [assembly: AssemblyTitle("Il2CppInteropFix.Patcher")] [assembly: TargetPlatform("Windows7.0")] [assembly: SupportedOSPlatform("Windows7.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Il2CppInteropFix { internal static class FixLogger { internal static ManualLogSource Log { get; private set; } internal static bool Verbose => Environment.GetEnvironmentVariable("IL2CPP_INTEROP_FIX_VERBOSE") == "1"; internal static void Initialize(ManualLogSource log) { Log = log; } internal static void Info(string message) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)message); } } internal static void Warning(string message) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)message); } } internal static void Debug(string message) { if (Verbose) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)message); } } } internal static void Error(string message) { ManualLogSource log = Log; if (log != null) { log.LogError((object)message); } } } [PatcherPluginInfo("com.slide.il2cppinteropfix.bootstrap", "Il2CppInterop Fix Bootstrap", "1.0.0")] internal sealed class Il2CppInteropFixBootstrap : BasePatcher { private static readonly object ApplyLock = new object(); private static Harmony _harmony; private static bool _chainloaderPatched; private static ManualLogSource _log; public override void Initialize() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown _log = ((BasePatcher)this).Log; FixLogger.Initialize(_log); _harmony = new Harmony("com.slide.il2cppinteropfix.bootstrap"); AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { OnAssemblyLoaded(assemblies[i]); } } public override void Finalizer() { TryPatchChainloader(); TryApplyLookupPatch("preloader Finalizer"); } private static void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { OnAssemblyLoaded(args.LoadedAssembly); } private static void OnAssemblyLoaded(Assembly assembly) { string name = assembly.GetName().Name; if ((name == "Il2CppInterop.Runtime" || name == "BepInEx.Unity.IL2CPP") ? true : false) { TryApplyLookupPatch("after " + name + " load"); TryPatchChainloader(); } } private static void TryApplyLookupPatch(string stage) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown lock (ApplyLock) { if (NestedTypeLookupFix.IsLookupPatchInstalled || !AppDomain.CurrentDomain.GetAssemblies().Any((Assembly assembly) => assembly.GetName().Name == "Il2CppInterop.Runtime")) { return; } if (NestedTypeLookupFix.TryInstallLookupPatch(_harmony)) { ManualLogSource log = _log; if (log != null) { bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Il2CppInterop nested-type injection fix applied ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(stage); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")."); } log.LogInfo(val); } } else { ManualLogSource log2 = _log; if (log2 != null) { log2.LogWarning((object)("Il2CppInterop nested-type injection fix was NOT applied (" + stage + "). Ensure Il2CppInteropFix.Patcher.dll is in BepInEx/patchers.")); } } } } private static void TryPatchChainloader() { //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Expected O, but got Unknown //IL_020f: Expected O, but got Unknown lock (ApplyLock) { if (_chainloaderPatched) { return; } Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly2) => assembly2.GetName().Name == "BepInEx.Unity.IL2CPP"); if (assembly == null) { return; } Type type = assembly.GetType("BepInEx.Unity.IL2CPP.Il2CppInteropManager", throwOnError: false); Type type2 = assembly.GetType("BepInEx.Unity.IL2CPP.IL2CPPChainloader", throwOnError: false); MethodInfo methodInfo = type?.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo2 = type?.GetMethod("PreloadInteropAssemblies", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo3 = type2?.GetMethod("LoadPlugin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(PluginInfo), typeof(Assembly) }, null); if (methodInfo == null && methodInfo2 == null && methodInfo3 == null) { ManualLogSource log = _log; if (log != null) { log.LogDebug((object)("Il2CppInterop fix bootstrap: chainloader methods not ready yet " + $"(managerType={type != null}, chainloaderType={type2 != null}).")); } return; } if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Il2CppInteropFixBootstrap), "BeforeInteropInitialize", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Il2CppInteropFixBootstrap), "AfterPreloadInteropAssemblies", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo3 != null) { _harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(Il2CppInteropFixBootstrap), "BeforePluginLoad", (Type[])null), new HarmonyMethod(typeof(Il2CppInteropFixBootstrap), "AfterPluginLoad", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _chainloaderPatched = true; ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)"Il2CppInterop fix bootstrap installed (pre-plugin)."); } } } public static void BeforeInteropInitialize() { TryApplyLookupPatch("before Il2CppInteropManager.Initialize"); } public static void AfterPreloadInteropAssemblies() { TryApplyLookupPatch("after PreloadInteropAssemblies"); } public static void BeforePluginLoad() { TryPatchChainloader(); TryApplyLookupPatch("before plugin Load"); } public static void AfterPluginLoad(PluginInfo pluginInfo, Assembly pluginAssembly) { string text = pluginAssembly?.GetName().Name ?? string.Empty; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(18, 2); defaultInterpolatedStringHandler.AppendLiteral("Plugin loaded: "); object value; if (pluginInfo == null) { value = null; } else { BepInPlugin metadata = pluginInfo.Metadata; value = ((metadata != null) ? metadata.Name : null); } defaultInterpolatedStringHandler.AppendFormatted((string?)value); defaultInterpolatedStringHandler.AppendLiteral(" ("); defaultInterpolatedStringHandler.AppendFormatted(text); defaultInterpolatedStringHandler.AppendLiteral(")"); FixLogger.Debug(defaultInterpolatedStringHandler.ToStringAndClear()); if (string.Equals(text, "BotControl", StringComparison.Ordinal)) { NestedTypeLookupFix.LogBotControlSummary(); } } } internal sealed class NestedTypeDiagnostics { private readonly List<string> _events = new List<string>(); private readonly Dictionary<string, string> _shortNameOwners = new Dictionary<string, string>(StringComparer.Ordinal); private readonly Dictionary<string, List<string>> _computedFullNames = new Dictionary<string, List<string>>(StringComparer.Ordinal); internal int LookupQualifiedAdded; internal int LookupShortAdded; internal int LookupShortSkipped; internal int DeclaringLinkOk; internal int DeclaringLinkFailed; internal void RecordEvent(string line) { _events.Add(line); FixLogger.Debug(line); } internal void RecordShortNameOwner(string namespaze, string shortName, string ownerType, IntPtr image) { string key = $"{namespaze}|{shortName}|{image.ToInt64():X}"; _shortNameOwners[key] = ownerType; } internal bool TryGetShortNameOwner(string namespaze, string shortName, IntPtr image, out string ownerType) { string key = $"{namespaze}|{shortName}|{image.ToInt64():X}"; return _shortNameOwners.TryGetValue(key, out ownerType); } internal void RecordComputedFullName(string fullName, string managedType) { if (!_computedFullNames.TryGetValue(fullName, out var value)) { value = new List<string>(); _computedFullNames[fullName] = value; } value.Add(managedType); } internal string BuildSummary() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("--- Il2CppInteropFix BotControl nested-type summary ---"); StringBuilder stringBuilder2 = stringBuilder; StringBuilder stringBuilder3 = stringBuilder2; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(46, 3, stringBuilder2); handler.AppendLiteral("Lookup: qualified="); handler.AppendFormatted(LookupQualifiedAdded); handler.AppendLiteral(", shortAdded="); handler.AppendFormatted(LookupShortAdded); handler.AppendLiteral(", shortSkipped="); handler.AppendFormatted(LookupShortSkipped); stringBuilder3.AppendLine(ref handler); stringBuilder2 = stringBuilder; StringBuilder stringBuilder4 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(32, 2, stringBuilder2); handler.AppendLiteral("DeclaringType link: ok="); handler.AppendFormatted(DeclaringLinkOk); handler.AppendLiteral(", failed="); handler.AppendFormatted(DeclaringLinkFailed); stringBuilder4.AppendLine(ref handler); foreach (KeyValuePair<string, List<string>> computedFullName in _computedFullNames) { if (computedFullName.Value.Count > 1) { stringBuilder2 = stringBuilder; StringBuilder stringBuilder5 = stringBuilder2; handler = new StringBuilder.AppendInterpolatedStringHandler(26, 2, stringBuilder2); handler.AppendLiteral("DUPLICATE full name '"); handler.AppendFormatted(computedFullName.Key); handler.AppendLiteral("' -> "); handler.AppendFormatted(string.Join(", ", computedFullName.Value)); stringBuilder5.AppendLine(ref handler); } } if (_events.Count > 0 && FixLogger.Verbose) { stringBuilder.AppendLine("Per-type trace:"); foreach (string @event in _events) { stringBuilder.AppendLine(" " + @event); } } stringBuilder.Append("--- end summary ---"); return stringBuilder.ToString(); } } internal static class NestedTypeLookupFix { private const Il2CppClassAttributes VisibilityMask = (Il2CppClassAttributes)7u; private const Il2CppClassAttributes NestedPublic = (Il2CppClassAttributes)2u; private const Il2CppClassAttributes NestedPrivate = (Il2CppClassAttributes)3u; private const string TargetAssemblyName = "BotControl"; private static readonly object InstallLock = new object(); private static bool _lookupPatchInstalled; private static bool _registerPatchInstalled; private static FieldInfo _injectedTypesField; private static NestedTypeDiagnostics _botControlDiagnostics; internal static bool IsLookupPatchInstalled => _lookupPatchInstalled; internal static void LogBotControlSummary() { NestedTypeDiagnostics botControlDiagnostics = _botControlDiagnostics; if (botControlDiagnostics == null) { FixLogger.Info("BotControl finished loading; no nested BotControl types were intercepted by Il2CppInteropFix."); } else { FixLogger.Info(botControlDiagnostics.BuildSummary()); } } internal static bool ShouldPassThroughToStock(Type type) { if (type == null || type.DeclaringType == null) { return true; } Assembly assembly = type.Assembly; string text = assembly.GetName().Name ?? string.Empty; if (text.StartsWith("Il2CppInterop.", StringComparison.Ordinal)) { return true; } string location = assembly.Location; if (!string.IsNullOrEmpty(location)) { string text2 = location.Replace('/', '\\'); if (text2.Contains("\\interop\\", StringComparison.OrdinalIgnoreCase) || text2.Contains("\\patchers\\", StringComparison.OrdinalIgnoreCase)) { return true; } } if (!string.Equals(text, "BotControl", StringComparison.Ordinal)) { return true; } return !IsInjectedType(type); } internal static bool TryInstallLookupPatch(Harmony harmony) { lock (InstallLock) { if (_lookupPatchInstalled) { return true; } if (!TryPatchAddTypeToLookup(harmony)) { FixLogger.Error("Failed to patch InjectorHelpers.AddTypeToLookup."); return false; } if (!TryPatchRegisterTypeInIl2Cpp(harmony)) { FixLogger.Warning("AddTypeToLookup patched, but RegisterTypeInIl2Cpp postfix was not installed."); } _lookupPatchInstalled = true; FixLogger.Info("Patches installed: AddTypeToLookup=yes, RegisterTypeInIl2Cpp=" + (_registerPatchInstalled ? "yes" : "no") + ". Set env IL2CPP_INTEROP_FIX_VERBOSE=1 for per-type trace."); return true; } } private static bool TryPatchRegisterTypeInIl2Cpp(Harmony harmony) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (_registerPatchInstalled) { return true; } Type type = FindLoadedType("Il2CppInterop.Runtime.Injection.ClassInjector"); Type type2 = FindLoadedType("Il2CppInterop.Runtime.Injection.RegisterTypeOptions"); if (type == null || type2 == null) { FixLogger.Warning("RegisterTypeInIl2Cpp patch skipped: ClassInjector types not found."); return false; } MethodInfo methodInfo = AccessTools.Method(type, "RegisterTypeInIl2Cpp", new Type[2] { typeof(Type), type2 }, (Type[])null); if (methodInfo == null) { FixLogger.Warning("RegisterTypeInIl2Cpp patch skipped: target method not found."); return false; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(NestedTypeLookupFix), "RegisterTypeInIl2CppPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _registerPatchInstalled = true; return true; } internal static void RegisterTypeInIl2CppPostfix(Type type) { if (!ShouldPassThroughToStock(type)) { NestedTypeDiagnostics botControlDiagnostics = GetBotControlDiagnostics(); string computedFullName; string text = TryLinkNestedDeclaringType(type, out computedFullName); if (text == "ok") { botControlDiagnostics.DeclaringLinkOk++; } else { botControlDiagnostics.DeclaringLinkFailed++; } botControlDiagnostics.RecordComputedFullName(computedFullName, type.FullName ?? type.Name); botControlDiagnostics.RecordEvent($"Register {type.FullName}: DeclaringType={text}, il2cppFullName='{computedFullName}'"); FixLogger.Info($"Nested register {type.Name} on {type.DeclaringType?.Name}: DeclaringType {text}, fullName='{computedFullName}'"); } } private unsafe static string TryLinkNestedDeclaringType(Type type, out string computedFullName) { computedFullName = string.Empty; try { Type declaringType = type.DeclaringType; if (declaringType == null) { return "no-managed-declaring-type"; } IntPtr nativeClassPointer = Il2CppClassPointerStore.GetNativeClassPointer(type); IntPtr nativeClassPointer2 = Il2CppClassPointerStore.GetNativeClassPointer(declaringType); if (nativeClassPointer == IntPtr.Zero) { return "native-class-missing"; } if (nativeClassPointer2 == IntPtr.Zero) { return "parent-not-registered-yet (" + declaringType.FullName + ")"; } INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)nativeClassPointer); computedFullName = BuildIl2CppFullName((Il2CppClass*)(void*)nativeClassPointer); val.DeclaringType = (Il2CppClass*)(void*)nativeClassPointer2; if (val.DeclaringType == null) { return "declaring-type-set-null"; } ref Il2CppClassAttributes flags = ref val.Flags; flags = (Il2CppClassAttributes)((uint)flags & 0xFFFFFFF8u); ref Il2CppClassAttributes flags2 = ref val.Flags; flags2 = (Il2CppClassAttributes)((uint)flags2 | (uint)(type.IsNestedPublic ? 2 : 3)); computedFullName = BuildIl2CppFullName((Il2CppClass*)(void*)nativeClassPointer); return "ok"; } catch (Exception ex) { FixLogger.Warning($"DeclaringType link failed for {type.FullName}: {ex.GetType().Name}: {ex.Message}"); return "exception:" + ex.GetType().Name; } } private unsafe static string BuildIl2CppFullName(Il2CppClass* classPointer) { try { Stack<string> stack = new Stack<string>(); INativeClassStruct val = UnityVersionHandler.Wrap(classPointer); INativeClassStruct val2 = val; do { stack.Push(Marshal.PtrToStringUTF8(val.Name) ?? string.Empty); val2 = val; } while ((val = UnityVersionHandler.Wrap(val.DeclaringType)) != null); string text = ((val2.Namespace != IntPtr.Zero) ? (Marshal.PtrToStringUTF8(val2.Namespace) ?? string.Empty) : string.Empty); StringBuilder stringBuilder = new StringBuilder(); if (text.Length > 0) { stringBuilder.Append(text).Append('.'); } stringBuilder.Append(string.Join("+", stack)); return stringBuilder.ToString(); } catch (Exception ex) { return "<full-name-error:" + ex.GetType().Name + ">"; } } private static Type FindLoadedType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } return AccessTools.TypeByName(fullName); } private static bool TryPatchAddTypeToLookup(Harmony harmony) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(FindLoadedType("Il2CppInterop.Runtime.Injection.InjectorHelpers"), "AddTypeToLookup", new Type[2] { typeof(Type), typeof(IntPtr) }, (Type[])null); if (methodInfo == null) { return false; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(NestedTypeLookupFix), "AddTypeToLookupPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return true; } internal static bool AddTypeToLookupPrefix(Type type, IntPtr typePointer) { if (ShouldPassThroughToStock(type)) { return true; } AddTypeToLookupImpl(type, typePointer); return false; } internal static void AddTypeToLookupImpl(Type type, IntPtr typePointer) { if (!TryBuildLookupNames(type, out var namespaze, out var klass)) { FixLogger.Warning("Lookup skipped for " + type?.FullName + ": could not build names."); return; } FieldInfo fieldInfo = AccessTools.Field(FindLoadedType("Il2CppInterop.Runtime.Injection.InjectorHelpers"), "s_ClassNameLookup"); if (fieldInfo == null) { FixLogger.Warning("s_ClassNameLookup field not found."); return; } Dictionary<(string, string, IntPtr), IntPtr> dict = (Dictionary<(string, string, IntPtr), IntPtr>)fieldInfo.GetValue(null); string name = type.Name; NestedTypeDiagnostics botControlDiagnostics = GetBotControlDiagnostics(); int num = 0; int num2 = 0; int num3 = 0; string text = null; lock (InstallLock) { foreach (IntPtr targetImage in GetTargetImages(type)) { if (TryAddLookupEntry(dict, namespaze, klass, targetImage, typePointer)) { num++; botControlDiagnostics.LookupQualifiedAdded++; } if (string.IsNullOrEmpty(name) || string.Equals(name, klass, StringComparison.Ordinal)) { continue; } if (TryAddLookupEntry(dict, namespaze, name, targetImage, typePointer)) { num2++; botControlDiagnostics.LookupShortAdded++; botControlDiagnostics.RecordShortNameOwner(namespaze, name, type.FullName ?? type.Name, targetImage); continue; } num3++; botControlDiagnostics.LookupShortSkipped++; if (text == null && botControlDiagnostics.TryGetShortNameOwner(namespaze, name, targetImage, out var ownerType)) { text = ownerType; } } } if (num3 > 0) { FixLogger.Warning($"Short lookup '{namespaze}.{name}' owned by '{text ?? "?"}'; skipped for '{type.FullName}' ({num3} images). Qualified key '{klass}' still added."); } botControlDiagnostics.RecordEvent($"Lookup {type.FullName}: klass='{klass}', images={num}, short +{num2}/skip{num3}, ptr=0x{typePointer.ToInt64():X}"); FixLogger.Info($"Lookup {type.Name}: qualified on {num} image(s), short +{num2} skip {num3}"); } private static bool TryAddLookupEntry(Dictionary<(string, string, IntPtr), IntPtr> dict, string namespaze, string klass, IntPtr image, IntPtr typePointer) { (string, string, IntPtr) key = (namespaze, klass, image); if (dict.ContainsKey(key)) { return false; } dict.Add(key, typePointer); return true; } internal static bool TryBuildLookupNames(Type type, out string namespaze, out string klass) { namespaze = string.Empty; klass = string.Empty; if (type == null) { return false; } Stack<string> stack = new Stack<string>(); Type type2 = type; while (type2 != null) { stack.Push(type2.Name); type2 = type2.DeclaringType; } klass = ((stack.Count <= 1) ? type.Name : string.Join("+", stack)); if (string.IsNullOrEmpty(klass)) { return false; } namespaze = type.Namespace ?? string.Empty; return true; } private static NestedTypeDiagnostics GetBotControlDiagnostics() { if (_botControlDiagnostics == null) { _botControlDiagnostics = new NestedTypeDiagnostics(); } return _botControlDiagnostics; } private static bool IsInjectedType(Type type) { FieldInfo injectedTypesField = GetInjectedTypesField(); if (injectedTypesField == null || (object)type == null || type.FullName == null) { return false; } object value = injectedTypesField.GetValue(null); if (value is ICollection<string> collection) { return collection.Contains(type.FullName); } if (value is IEnumerable enumerable) { foreach (object item in enumerable) { if (item is string text && text == type.FullName) { return true; } } } return false; } private static FieldInfo GetInjectedTypesField() { if (_injectedTypesField != null) { return _injectedTypesField; } Type type = FindLoadedType("Il2CppInterop.Runtime.Injection.ClassInjector"); _injectedTypesField = ((type == null) ? null : AccessTools.Field(type, "InjectedTypes")); return _injectedTypesField; } private static IEnumerable<IntPtr> GetTargetImages(Type type) { Type type2 = FindLoadedType("Il2CppInterop.Runtime.Attributes.ClassInjectionAssemblyTargetAttribute"); Attribute attribute = ((type2 == null) ? null : Attribute.GetCustomAttribute(type, type2)); if (attribute == null) { MethodInfo methodInfo = AccessTools.Method(typeof(IL2CPP), "GetIl2CppImages", (Type[])null, (Type[])null); if (!(methodInfo == null)) { return (IEnumerable<IntPtr>)methodInfo.Invoke(null, null); } return Array.Empty<IntPtr>(); } return (IEnumerable<IntPtr>)AccessTools.Method(attribute.GetType(), "GetImagePointers", (Type[])null, (Type[])null).Invoke(attribute, null); } } }
SlidesBotControl - V1.2.3.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.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using AIGraph; using AK; using Agents; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP.Hook; using BepInEx.Unity.IL2CPP.Utils; using BepInEx.Unity.IL2CPP.Utils.Collections; using BetterBots.Components; using BetterBots.Managers; using BotControl; using BotControl.CustomActions; using BotControl.CustomActions.CustomActions; using BotControl.CustomActions.Patches; using BotControl.Menus; using BotControl.Networking; using BotControl.Patches; using BotControl.SmartSelect; using BotControl.SmartSelect.PressActions; using BotControl.SmartSelect.PressActions.DoubleTapActions; using BotControl.SmartSelect.PressTypes; using CellMenu; using ChainedPuzzles; using CollisionRundown.Features.HUDs; using CullingSystem; using Enemies; using ExteriorRendering; using FluffyUnderware.DevTools.Extensions; using GTFO.API; using GameData; using Gear; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.Runtime; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Assembly; using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using LevelGeneration; using Localization; using Microsoft.CodeAnalysis; using Player; using PrioritySet; using SNetwork; using SlideDrum; using SlideDrum.sInputSystem; using SlideMenu; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("BotControl")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+gitd5013ac-dirty-dev.d5013acaeca679836731ad818ee8d06830e6585a")] [assembly: AssemblyProduct("BotControl")] [assembly: AssemblyTitle("BotControl")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal delegate void <>f__AnonymousDelegate0<T1, T2, T3>(T1 arg1, T2 arg2 = default(T2), T3 arg3 = default(T3)); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate1<T1>(T1 arg = default(T1)); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate2<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3 = 0.1f); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate3<T1>(T1 arg = true); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate4<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3 = false); [CompilerGenerated] internal delegate TResult <>f__AnonymousDelegate5<T1, T2, TResult>(T1 arg1, T2 arg2 = 0uL); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate6<T1, T2, T3>(T1 arg1, T2 arg2 = false, T3 arg3 = default(T3)); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate7<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3 = default(T3), T4 arg4 = default(T4)); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate8<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3 = 10); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate9<T1, T2, T3, T4>(T1 arg1 = default(T1), T2 arg2 = default(T2), T3 arg3 = 0uL, T4 arg4 = default(T4)); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate10<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3 = ""); [CompilerGenerated] internal delegate void <>f__AnonymousDelegate11<T1, T2>(T1 arg1, T2 arg2 = default(T2)); namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class CustomActionRegistry { private static readonly (Type ActionType, Func<PlayerAIBot, CustomActionBase.Descriptor> CreateDescriptor)[] Actions; static CustomActionRegistry() { Actions = (from t in typeof(CustomActionBase).Assembly.GetTypes() where t.IsClass && !t.IsAbstract && typeof(CustomActionBase).IsAssignableFrom(t) select (Action: t, Descriptor: t.GetNestedType("Descriptor", BindingFlags.Public | BindingFlags.NonPublic)) into pair where pair.Descriptor != null && typeof(CustomActionBase.Descriptor).IsAssignableFrom(pair.Descriptor) && !pair.Descriptor.IsAbstract select (Action: pair.Action, CreateDescriptorFactory(pair.Descriptor))).ToArray(); } private static Func<PlayerAIBot, CustomActionBase.Descriptor> CreateDescriptorFactory(Type descriptorType) { ConstructorInfo? constructor = descriptorType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(PlayerAIBot) }, null); if (constructor == null) { throw new InvalidOperationException("No (PlayerAIBot) constructor on " + descriptorType.FullName); } ParameterExpression parameterExpression = Expression.Parameter(typeof(PlayerAIBot), "bot"); return Expression.Lambda<Func<PlayerAIBot, CustomActionBase.Descriptor>>(Expression.New(constructor, parameterExpression), new ParameterExpression[1] { parameterExpression }).Compile(); } public static void RegisterIl2CppTypes() { ClassInjector.RegisterTypeInIl2Cpp(typeof(CustomActionBase)); ClassInjector.RegisterTypeInIl2Cpp(typeof(CustomActionBase.Descriptor)); (Type, Func<PlayerAIBot, CustomActionBase.Descriptor>)[] actions = Actions; for (int i = 0; i < actions.Length; i++) { Type item = actions[i].Item1; ClassInjector.RegisterTypeInIl2Cpp(item); ClassInjector.RegisterTypeInIl2Cpp(item.GetNestedType("Descriptor", BindingFlags.Public | BindingFlags.NonPublic)); } } public static void Setup(PlayerAIBot bot) { if ((Object)(object)bot == (Object)null) { throw new ArgumentNullException("bot"); } dataStore orCreateData = zActions.GetOrCreateData(bot); (Type, Func<PlayerAIBot, CustomActionBase.Descriptor>)[] actions = Actions; for (int i = 0; i < actions.Length; i++) { CustomActionBase.Descriptor descriptor = actions[i].Item2(bot); if ((Object)(object)((Descriptor)descriptor).Bot == (Object)null) { ((Descriptor)descriptor).Bot = bot; } CustomActionBase customActionBase = (CustomActionBase)(object)((Descriptor)descriptor).CreateAction(); orCreateData.customActionDescriptors.Add(descriptor, (int?)null, (ConflictResolution?)null, (DuplicateValuePolicy?)null, (PlacementIndexBias?)null); orCreateData.customActionBases.Add(customActionBase, (int?)null, (ConflictResolution?)null, (DuplicateValuePolicy?)null, (PlacementIndexBias?)null); } } } [HarmonyPatch] public static class UnlockActionPatch { private static float s_hackSuccessChance = 0.25f; private static int s_hackMaxNrFaults = 3; private const uint LockMelterBackpackItemId = 116u; private const uint HackingToolBackpackItemId = 53u; private static bool useNewMethod = true; [HarmonyPatch(typeof(PlayerBotActionUnlock), "ChooseMethod")] [HarmonyPrefix] public static bool PreChooseMethod(PlayerBotActionUnlock __instance, ref bool __result) { if (!useNewMethod) { return true; } __result = ChooseMethod(__instance); return false; } private static EventDelegateFunc CreateEventDelegate(PlayerBotActionUnlock action) { return DelegateSupport.ConvertDelegate<EventDelegateFunc>((Delegate)new Action<Descriptor>(action.OnMethodActionEvent)); } private static bool ChooseMethod(PlayerBotActionUnlock action) { //IL_0001: 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_0029: Expected I4, but got Unknown //IL_0072: 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_0044: Unknown result type (might be due to invalid IL or missing references) if ((int)action.m_method != 0) { return CommitChosenMethod(action); } if (action.m_desc == null) { throw new NullReferenceException(); } int num = (int)action.m_desc.Method; if (UsesFlagResolution(num)) { if (TryResolveFlagMethod(action, num, out var resolved)) { action.m_method = resolved; if (!TryAssignMethodDescriptor(action, resolved)) { return false; } return CommitChosenMethod(action); } action.m_method = (MethodEnum)0; return false; } action.m_method = (MethodEnum)num; if (num == 0) { MarkDescriptorFailed(action); return false; } if (!TryAssignMethodDescriptor(action, action.m_method)) { return false; } return CommitChosenMethod(action); } private static bool CommitChosenMethod(PlayerBotActionUnlock action) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (action.m_desc == null) { throw new NullReferenceException(); } action.m_desc.UsedMethod = action.m_method; return true; } private static void MarkDescriptorFailed(PlayerBotActionUnlock action) { if (action.m_desc == null) { throw new NullReferenceException(); } ((Descriptor)action.m_desc).SetCompletionStatus((StatusType)4); } private static bool UsesFlagResolution(int descriptorMethod) { if (descriptorMethod == 7) { return true; } return (descriptorMethod & (descriptorMethod - 1)) != 0; } private static bool TryResolveFlagMethod(PlayerBotActionUnlock action, int methodFlags, out MethodEnum resolved) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Invalid comparison between Unknown and I4 //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Invalid comparison between Unknown and I4 resolved = (MethodEnum)0; action.m_method = (MethodEnum)methodFlags; LG_WeakLock val = action.m_desc.Lock; PlayerAIBot bot = ((PlayerBotActionBase)action).m_bot; if ((Object)(object)bot == (Object)null) { throw new NullReferenceException(); } if (!bot.WantsCrouch() && (methodFlags & 1) != 0) { if (bot.Backpack == null) { throw new NullReferenceException(); } BackpackItem val2 = default(BackpackItem); if (bot.Backpack.TryGetBackpackItem((InventorySlot)10, ref val2)) { if ((Object)(object)val == (Object)null) { throw new NullReferenceException(); } if ((int)val.Status == 0) { resolved = (MethodEnum)1; return true; } } } if ((methodFlags & 2) != 0) { if (bot.Backpack == null) { throw new NullReferenceException(); } BackpackItem val3 = default(BackpackItem); if (bot.Backpack.TryGetBackpackItem((InventorySlot)11, ref val3)) { if (val3 == null) { throw new NullReferenceException(); } if (val3.ItemID == 53) { if ((Object)(object)val == (Object)null) { throw new NullReferenceException(); } if ((int)val.Status == 1) { resolved = (MethodEnum)2; return true; } } } } if ((methodFlags & 4) != 0) { if (bot.Backpack == null) { throw new NullReferenceException(); } BackpackItem val4 = default(BackpackItem); if (bot.Backpack.TryGetBackpackItem((InventorySlot)5, ref val4)) { if (val4 == null) { throw new NullReferenceException(); } if (val4.ItemID == 116) { if ((Object)(object)val == (Object)null) { throw new NullReferenceException(); } eWeakLockStatus status = val.Status; if ((int)status == 0 || (int)status == 1) { resolved = (MethodEnum)4; return true; } } } } return false; } private static bool TryAssignMethodDescriptor(PlayerBotActionUnlock action, MethodEnum method) { //IL_0000: 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_0018: Expected I4, but got Unknown switch (method - 1) { case 0: { if (!TryCreateMeleeDescriptor(action, out var descriptor)) { return false; } action.m_chosenMethod = descriptor; return true; } case 1: action.m_chosenMethod = (Descriptor)(object)CreateHackDescriptor(action); return true; case 3: action.m_chosenMethod = (Descriptor)(object)CreateMeltDescriptor(action); return true; default: MarkDescriptorFailed(action); return false; } } private static bool TryCreateMeleeDescriptor(PlayerBotActionUnlock action, out Descriptor descriptor) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown descriptor = null; if (((PlayerBotActionBase)action).m_backpack == null) { throw new NullReferenceException(); } BackpackItem val = default(BackpackItem); if (!((PlayerBotActionBase)action).m_backpack.TryGetBackpackItem((InventorySlot)10, ref val)) { return false; } if (val == null) { throw new NullReferenceException(); } MeleeWeaponThirdPerson weapon = ((Il2CppObjectBase)val.Instance).TryCast<MeleeWeaponThirdPerson>(); Descriptor val2 = new Descriptor(((PlayerBotActionBase)action).m_bot); ((Descriptor)val2).ParentActionBase = (PlayerBotActionBase)(object)action; ((Descriptor)val2).Prio = ((Descriptor)action.m_desc).Prio; ((Descriptor)val2).EventDelegate = CreateEventDelegate(action); val2.Haste = 0.75f; val2.Force = 1f; val2.Strike = true; val2.Loop = true; val2.Travel = true; if (action.m_desc == null) { throw new NullReferenceException(); } LG_WeakLock obj = action.m_desc.Lock; if ((Object)(object)obj == (Object)null) { throw new NullReferenceException(); } LG_WeakLockDamage componentInChildren = ((Component)obj).GetComponentInChildren<LG_WeakLockDamage>(); if ((Object)(object)componentInChildren == (Object)null) { throw new NullReferenceException(); } val2.TargetGameObject = ((Component)componentInChildren).gameObject; val2.Weapon = weapon; descriptor = (Descriptor)(object)val2; return true; } private static Descriptor CreateHackDescriptor(PlayerBotActionUnlock action) { //IL_0006: 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_0012: 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_003d: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown Descriptor val = new Descriptor(((PlayerBotActionBase)action).m_bot) { ParentActionBase = (PlayerBotActionBase)(object)action, Prio = ((Descriptor)action.m_desc).Prio, EventDelegate = CreateEventDelegate(action) }; if (action.m_desc == null) { throw new NullReferenceException(); } val.Lock = action.m_desc.Lock; val.MaxNrFaults = s_hackMaxNrFaults; val.SuccessChance = s_hackSuccessChance; return val; } private static Descriptor CreateMeltDescriptor(PlayerBotActionUnlock action) { //IL_0006: 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_0012: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown Descriptor val = new Descriptor(((PlayerBotActionBase)action).m_bot) { ParentActionBase = (PlayerBotActionBase)(object)action, Prio = ((Descriptor)action.m_desc).Prio, EventDelegate = CreateEventDelegate(action) }; if (action.m_desc == null) { throw new NullReferenceException(); } val.Lock = action.m_desc.Lock; return val; } } [Flags] public enum CornerTag { None = 0, Top = 1, MiddleY = 2, Bottom = 4, Left = 8, MiddleX = 0x10, Right = 0x20, Front = 0x40, MiddleZ = 0x80, Back = 0x100, Center = 0x92, All = 0x1FF } public struct BoundingPoint { public Vector3 Position; public CornerTag Tags; public BoundingPoint(Vector3 pos, CornerTag tags) { //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) Position = pos; Tags = tags; } public bool Has(CornerTag tag) { return (Tags & tag) != 0; } public override string ToString() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) return $"{Tags}: {Position}"; } } public class BoundingBox { [Flags] public enum BoundingSource { None = 0, MeshFilters = 1, Renderers = 2, Colliders = 4, All = 7 } private readonly GameObject _go; private readonly List<BoundingPoint> _points = new List<BoundingPoint>(); private List<GameObject> _debugMarkers = new List<GameObject>(); public IEnumerable<BoundingPoint> Points => _points; public Vector3 Center { get; private set; } public Vector3 Size { get; private set; } public IEnumerable<Vector3> Front => GetCorners(CornerTag.Front); public IEnumerable<Vector3> Back => GetCorners(CornerTag.Back); public IEnumerable<Vector3> Top => GetCorners(CornerTag.Top); public IEnumerable<Vector3> Bottom => GetCorners(CornerTag.Bottom); public IEnumerable<Vector3> Left => GetCorners(CornerTag.Left); public IEnumerable<Vector3> Right => GetCorners(CornerTag.Right); public BoundingBox(GameObject go, BoundingSource sources = BoundingSource.All) { _go = go; Refresh(sources); } public void Refresh(BoundingSource sources = BoundingSource.All) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013b: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0486: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) Quaternion rotation = _go.transform.rotation; _go.transform.rotation = Quaternion.identity; Transform parent = _go.transform.parent; _go.transform.parent = null; _points.Clear(); Transform transform = _go.transform; List<Bounds> list = new List<Bounds>(); if (sources.HasFlag(BoundingSource.MeshFilters)) { foreach (MeshFilter componentsInChild in _go.GetComponentsInChildren<MeshFilter>()) { if (!((Object)(object)componentsInChild.mesh == (Object)null)) { Bounds bounds = componentsInChild.mesh.bounds; ((Bounds)(ref bounds)).center = transform.InverseTransformPoint(((Component)componentsInChild).transform.TransformPoint(((Bounds)(ref bounds)).center)); list.Add(bounds); } } } if (sources.HasFlag(BoundingSource.Renderers)) { foreach (Renderer componentsInChild2 in _go.GetComponentsInChildren<Renderer>()) { Bounds bounds2 = componentsInChild2.bounds; ((Bounds)(ref bounds2)).center = transform.InverseTransformPoint(((Bounds)(ref bounds2)).center); list.Add(bounds2); } } if (sources.HasFlag(BoundingSource.Colliders)) { foreach (Collider componentsInChild3 in _go.GetComponentsInChildren<Collider>()) { Bounds bounds3 = componentsInChild3.bounds; ((Bounds)(ref bounds3)).center = transform.InverseTransformPoint(((Bounds)(ref bounds3)).center); list.Add(bounds3); } } if (list.Count == 0) { Vector3 pos = (Center = transform.position); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { CornerTag cornerTag = CornerTag.None; cornerTag = (CornerTag)((int)cornerTag | (i switch { 1 => 16, 0 => 8, _ => 32, })); cornerTag = (CornerTag)((int)cornerTag | (j switch { 1 => 2, 0 => 4, _ => 1, })); cornerTag = (CornerTag)((int)cornerTag | (k switch { 1 => 128, 0 => 256, _ => 64, })); _points.Add(new BoundingPoint(pos, cornerTag)); } } } _go.transform.rotation = rotation; return; } Bounds val = list[0]; foreach (Bounds item in list.Skip(1)) { Bounds current2 = item; ((Bounds)(ref val)).Encapsulate(((Bounds)(ref current2)).min); ((Bounds)(ref val)).Encapsulate(((Bounds)(ref current2)).max); } Size = ((Bounds)(ref val)).size; Center = transform.TransformPoint(((Bounds)(ref val)).center); Vector3 center = ((Bounds)(ref val)).center; Vector3 extents = ((Bounds)(ref val)).extents; float[] array = new float[3] { 0f - extents.x, 0f, extents.x }; float[] array2 = new float[3] { 0f - extents.y, 0f, extents.y }; float[] array3 = new float[3] { 0f - extents.z, 0f, extents.z }; for (int l = 0; l < 3; l++) { for (int m = 0; m < 3; m++) { for (int n = 0; n < 3; n++) { Vector3 val2 = center + new Vector3(array[l], array2[m], array3[n]); Vector3 pos2 = transform.TransformPoint(val2); CornerTag cornerTag2 = CornerTag.None; cornerTag2 = (CornerTag)((int)cornerTag2 | (l switch { 1 => 16, 0 => 8, _ => 32, })); cornerTag2 = (CornerTag)((int)cornerTag2 | (m switch { 1 => 2, 0 => 4, _ => 1, })); cornerTag2 = (CornerTag)((int)cornerTag2 | (n switch { 1 => 128, 0 => 256, _ => 64, })); _points.Add(new BoundingPoint(pos2, cornerTag2)); } } } _go.transform.rotation = rotation; _go.transform.parent = parent; for (int num = 0; num < _points.Count; num++) { Vector3 val3 = _points[num].Position - transform.position; Vector3 pos3 = rotation * val3 + transform.position; _points[num] = new BoundingPoint(pos3, _points[num].Tags); } Vector3 val4 = Vector3.zero; foreach (BoundingPoint point in _points) { val4 += point.Position; } Center = val4 / (float)_points.Count; } public bool IsInside(Vector3 worldPoint) { //IL_003d: 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_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_0054: 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_0061: 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) //IL_006f: 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_0079: 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_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_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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) BoundingPoint[] array = _points.Where((BoundingPoint p) => !p.Has(CornerTag.MiddleX) && !p.Has(CornerTag.MiddleY) && !p.Has(CornerTag.MiddleZ)).ToArray(); if (array.Length == 0) { return false; } Vector3 val = array[0].Position; Vector3 val2 = array[0].Position; for (int num = 1; num < array.Length; num++) { val = Vector3.Min(val, array[num].Position); val2 = Vector3.Max(val2, array[num].Position); } if (worldPoint.x >= val.x && worldPoint.x <= val2.x && worldPoint.y >= val.y && worldPoint.y <= val2.y) { if (worldPoint.z >= val.z) { return worldPoint.z <= val2.z; } return false; } return false; } public IEnumerable<Vector3> GetCorners(CornerTag include = CornerTag.All, CornerTag exclude = CornerTag.None) { foreach (BoundingPoint point in _points) { if (point.Has(include) && (exclude == CornerTag.None || !point.Has(exclude))) { yield return point.Position; } } } public IEnumerable<Vector3> CornersOnly() { foreach (BoundingPoint point in _points) { if (!point.Has(CornerTag.MiddleX) && !point.Has(CornerTag.MiddleY) && !point.Has(CornerTag.MiddleZ)) { yield return point.Position; } } } public void ToggleDebug() { if (_debugMarkers.Count == 0) { ShowDebug(); } else { ClearDebug(); } } public void ShowDebug(Transform parent = null, float size = 0.2f) { //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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_004a: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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) ClearDebug(); foreach (Vector3 corner in GetCorners()) { GameObject val = new GameObject("BB_DebugPoint"); if ((Object)(object)parent != (Object)null) { val.transform.parent = parent; } val.transform.position = corner; TextMesh obj = val.AddComponent<TextMesh>(); obj.text = "-"; obj.characterSize = size; obj.anchor = (TextAnchor)4; obj.alignment = (TextAlignment)1; obj.color = Color.red; zDebug.DrawLine(corner, Center, Color.white, 0.01f).transform.SetParent(val.transform, true); _debugMarkers.Add(val); } BoundingPoint? boundingPoint = _points.FirstOrDefault((BoundingPoint p) => p.Has(CornerTag.Top) && p.Has(CornerTag.MiddleX) && p.Has(CornerTag.MiddleZ)); if (boundingPoint.HasValue) { GameObject val2 = new GameObject("BB_DebugLabel"); if ((Object)(object)parent != (Object)null) { val2.transform.parent = parent; } val2.transform.position = boundingPoint.Value.Position + Vector3.up * 0.1f; val2.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f); _debugMarkers.Add(val2); } } public void ClearDebug() { foreach (GameObject debugMarker in _debugMarkers) { if ((Object)(object)debugMarker != (Object)null) { Object.Destroy((Object)(object)debugMarker); } } _debugMarkers.Clear(); } } namespace CollisionRundown.Features.HUDs { internal static class InGameTitle { public static PUI_InteractionPrompt Prompt; private static readonly Regex s_StripRichTextRegex = new Regex("\\<.+?\\>"); private static int s_SmallTitleLength; private static int s_TitleLength; public static void DisplayDefault() { ((TMP_Text)Prompt.m_headerText).maxVisibleCharacters = 0; ((RectTransformComp)Prompt).SetVisible(true); CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(DoDefaultDisplay()), (Action)null); } public static void SetTitle(string smallTitle, string title) { string text = s_StripRichTextRegex.Replace(smallTitle, ""); SetLength(titleLength: s_StripRichTextRegex.Replace(title, "").Length, smallTitleLength: text.Length); SetText(smallTitle + "\n<b><size=200%>" + title); } public static void SetLength(int smallTitleLength, int titleLength) { s_SmallTitleLength = smallTitleLength; s_TitleLength = titleLength; } private static IEnumerator DoDefaultDisplay() { ((TMP_Text)Prompt.m_headerText).alpha = 1f; ((TMP_Text)Prompt.m_headerText).maxVisibleCharacters = 0; Prompt.PlayIntro(); CM_PageBase.PostSound(EVENTS.HUD_SCAN_COMPLETE_INDICATION, "Display IGT"); yield return (object)new WaitForSeconds(0.33f); int visibleCount = 0; while (visibleCount <= s_SmallTitleLength) { visibleCount++; ((TMP_Text)Prompt.m_headerText).maxVisibleCharacters = visibleCount; CM_PageBase.PostSound(EVENTS.HUD_EXIT_SCAN_INFO_TEXT_DISAPPEAR, "Type IGT"); yield return (object)new WaitForSeconds(0.065f); } yield return (object)new WaitForSeconds(1f); while (visibleCount <= s_TitleLength + s_SmallTitleLength + 1) { visibleCount++; ((TMP_Text)Prompt.m_headerText).maxVisibleCharacters = visibleCount; CM_PageBase.PostSound(EVENTS.HUD_EXIT_SCAN_INFO_TEXT_DISAPPEAR, "Type IGT"); yield return (object)new WaitForSeconds(0.065f); } yield return (object)new WaitForSeconds(6.5f); CM_PageBase.PostSound(EVENTS.HUD_EXIT_SCAN_INFO_TEXT_APPEAR, "Hide IGT"); Prompt.PlayIntro(); yield return (object)new WaitForSeconds(0.33f); ((RectTransformComp)Prompt).SetVisible(false); } private static void SetText(string rawText) { ((TMP_Text)Prompt.m_headerText).SetText(rawText, true); } } [HarmonyPatch(typeof(InteractionGuiLayer), "Setup")] internal static class Patch_InteractionLayer_Setup { private static void Postfix(InteractionGuiLayer __instance) { //IL_0011: 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_0076: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) PUI_InteractionPrompt obj = ((Il2CppObjectBase)((GuiLayer)__instance).AddRectComp("Gui/Player/PUI_InteractionPrompt_CellUI", (GuiAnchor)3, new Vector2(0f, 258f), (Transform)null)).Cast<PUI_InteractionPrompt>(); ((Graphic)obj.m_headerText).color = Color.white; ((TMP_Text)obj.m_headerText).fontSize = 24.5f; ((TMP_Text)obj.m_headerText).fontSizeMin = 24.5f; ((TMP_Text)obj.m_headerText).fontSizeMax = 24.5f; ((TMP_Text)obj.m_headerText).rectTransform.sizeDelta = new Vector2(120f, -10f); obj.m_whiteBox.transform.localPosition = new Vector3(0f, -22.8f, 0f); obj.m_whiteBox.transform.localScale = new Vector3(1f, 1.35f, 1f); obj.m_whiteBoxWide.transform.localPosition = new Vector3(0f, -22.8f, 0f); obj.m_whiteBoxWide.transform.localScale = new Vector3(1f, 1.5f, 1f); obj.SetTimerFill(0f); ((RectTransformComp)obj).SetVisible(false); InGameTitle.Prompt = obj; InGameTitle.SetTitle("Small debug title here", "Beeeeg debug title here"); } } } namespace SlideMenu { public class FlexibleMethodDefinition { public Delegate method; public object[] args; public FlexibleMethodDefinition(Delegate method) { this.method = method; args = Array.Empty<object>(); } public FlexibleMethodDefinition(Delegate method, object[] args) { this.method = method; this.args = args; } public static implicit operator FlexibleMethodDefinition(Delegate d) { return new FlexibleMethodDefinition(d); } public object? Invoke() { return Invoke(args); } public object? Invoke(params object[] suppliedArgs) { if ((object)method == null) { throw new InvalidOperationException("No method assigned to FlexibleMethodDefinition."); } object[] array = ((suppliedArgs != null && suppliedArgs.Length != 0) ? suppliedArgs : args); try { return method.DynamicInvoke(array); } catch (TargetParameterCountException innerException) { throw new InvalidOperationException($"Parameter count mismatch. Expected {method.Method.GetParameters().Length}, got {((array != null) ? array.Length : 0)}.", innerException); } catch (Exception inner) { throw new TargetInvocationException("Error invoking method '" + method.Method.Name + "'.", inner); } } } public class FlexibleEvent { private readonly OrderedSet<Action> listeners = new OrderedSet<Action>(); public FlexibleEvent Listen(Action method) { if (method == null) { return this; } listeners.Add(method); return this; } public FlexibleEvent Listen(FlexibleMethodDefinition method) { return Listen(method.method, method.args, method); } public FlexibleEvent Listen(Delegate method, object[] args, FlexibleMethodDefinition? fMethod = null) { if ((object)method == null) { return this; } ParameterInfo[] parameters = method.Method.GetParameters(); object[] finalArgs = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { if (i < args.Length && args[i] != new object()) { finalArgs[i] = args[i]; continue; } if (parameters[i].IsOptional) { finalArgs[i] = parameters[i].DefaultValue; continue; } throw new ArgumentException("Missing required argument '" + parameters[i].Name + "'"); } listeners.Add(Wrapper); return this; void Wrapper() { method.DynamicInvoke(finalArgs); if (fMethod?.args != null) { for (int j = 0; j < finalArgs.Length && j < fMethod.args.Length; j++) { fMethod.args[j] = finalArgs[j]; } } } } public void Unlisten(Action method) { listeners.Remove(method); } public void Unlisten(FlexibleMethodDefinition method) { listeners.Remove((Action)method.method); } public void ClearListeners() { listeners.Clear(); } public void Invoke() { foreach (Action listener in listeners) { listener(); } } } public class sMenu { public class sMenuNode { private class SelectionColorHandler { private sMenuNode node; private bool selected; private bool pressed; private static Color selectedOffset = new Color(0.1f, 0.1f, 0.1f); private static Color pressedOffset = new Color(0.3f, 0.2f, 0.5f); public SelectionColorHandler(sMenuNode Node) { node = Node; } internal void onClosed() { selected = false; pressed = false; UpdateOffset(); } internal void onSelected() { selected = true; UpdateOffset(); } internal void OnDeselected() { selected = false; UpdateOffset(); } internal void OnPressed() { pressed = true; UpdateOffset(); } internal void OnUnpressed() { pressed = false; UpdateOffset(); } private void UpdateOffset() { //IL_0015: 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_0038: 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) //IL_005b: Unknown result type (might be due to invalid IL or missing references) node.ColorOffset = new Color(0f, 0f, 0f); if (selected) { sMenuNode sMenuNode = node; sMenuNode.ColorOffset += selectedOffset; } if (pressed) { sMenuNode sMenuNode2 = node; sMenuNode2.ColorOffset += pressedOffset; } } } private string _title = ""; private string _subtitle = ""; private string _description = ""; private string _text = ""; private string _prefix = ""; private string _suffix = ""; public bool selected; public bool pressed; public bool held; public int frameFirstPressedAt = Time.frameCount; public float timeFirstPressedAt = Time.time; public int frameLastPressedAt = Time.frameCount; public float timeLastPressedAt = Time.time; public float lastTapTime = Time.time; public sMenu parrentMenu; private Dictionary<sMenuManager.nodeEvent, FlexibleEvent> _eventMap; public TextPart fullTextPart; public TextPart titlePart; public TextPart subtitlePart; public TextPart descriptionPart; public GameObject gameObject; private GameObject TextPartGameObject; private RectTransform rect; internal GameObject backgroundObject; internal RawImage backgroundImage; private SelectionColorHandler selectionColorHandler; private bool hasHoverText; private Color _color; private Color _colorOffset; private float holdThreshold = 0.2f; private float doubleTapThreshold = 0.3f; public string title { get { return _title.Trim(); } set { _title = value; UpdateTitle(); } } public string subtitle { get { return _subtitle.Trim(); } set { _subtitle = value; UpdateSubtitle(); } } public string description { get { return _description.Trim(); } set { _description = value; UpdateDescription(); } } public string text { get { return _text.Trim(); } set { _text = value; UpdateText(); } } public string prefix { get { return _prefix.Trim(); } set { _prefix = value; UpdateText(); } } public string suffix { get { return _suffix.Trim(); } set { _suffix = value; UpdateText(); } } public string fullText { get { return string.Join(" ", prefix, text, suffix).Trim(); } [Obsolete("\nDon't assign to fullText. Use vars \"prefix\", \"text\" and \"suffix\" instead.\nYou probably want var \"text\".", true)] set { } } public bool closeOnPress { get; private set; } private Dictionary<sMenuManager.nodeEvent, FlexibleEvent> eventMap { get { if (_eventMap == null) { _eventMap = new Dictionary<sMenuManager.nodeEvent, FlexibleEvent>(); sMenuManager.nodeEvent[] values = Enum.GetValues<sMenuManager.nodeEvent>(); foreach (sMenuManager.nodeEvent key in values) { _eventMap[key] = new FlexibleEvent(); } } return _eventMap; } } public Color color { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _color; } set { //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) //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_0017: Unknown result type (might be due to invalid IL or missing references) Color val = _color; _color = value; if (val != value) { SetColor(_color); } } } public Color ColorOffset { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _colorOffset; } set { //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) //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_0017: Unknown result type (might be due to invalid IL or missing references) Color colorOffset = _colorOffset; _colorOffset = value; if (colorOffset != value) { SetColor(_color); } } } public sMenuNode(string arg_Name, sMenu arg_parrentMenu, FlexibleMethodDefinition arg_Callback) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) gameObject = new GameObject("sMenuNode " + arg_Name); gameObject.transform.SetParent(((Component)arg_parrentMenu.getCanvas()).transform, false); backgroundObject = new GameObject("Background"); TextPartGameObject = new GameObject("TextParts"); TextPartGameObject.transform.SetParent(gameObject.transform, false); backgroundObject.transform.SetParent(gameObject.transform, false); backgroundObject.transform.localPosition = new Vector3(0f, 0f, 30f); backgroundImage = backgroundObject.AddComponent<RawImage>(); backgroundImage.texture = (Texture)(object)sMenuManager.DefaultBackgroundImage; rect = gameObject.AddComponent<RectTransform>(); RectTransform obj = rect; RectTransform obj2 = rect; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); obj2.anchorMax = val; obj.anchorMin = val; rect.anchoredPosition = Vector2.zero; ((Transform)rect).localScale = Vector3.one; parrentMenu = arg_parrentMenu; if (arg_Callback != null) { eventMap[sMenuManager.nodeEvent.OnUnpressedSelected].Listen(arg_Callback); } color = parrentMenu.getTextColor(); VerticalLayoutGroup obj3 = TextPartGameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj3).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)obj3).spacing = 2f; ((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false; ContentSizeFitter obj4 = TextPartGameObject.AddComponent<ContentSizeFitter>(); obj4.verticalFit = (FitMode)2; obj4.horizontalFit = (FitMode)2; ((Object)(titlePart = new TextPart(TextPartGameObject, title ?? "", new Color(0.2f, 0.2f, 0.2f, 1f), TextPart.TextPartType.Title).SetScale(0.75f, 0.75f)).gameObject).name = "Title"; ((Object)(fullTextPart = new TextPart(TextPartGameObject, text ?? "", parrentMenu.textColor, TextPart.TextPartType.Main)).gameObject).name = "Text"; ((Object)(subtitlePart = new TextPart(TextPartGameObject, title ?? "", new Color(0.1f, 0.1f, 0.1f, 1f), TextPart.TextPartType.Subtitle).SetScale(0.75f, 0.75f)).gameObject).name = "Subtitle"; ((Object)(descriptionPart = new TextPart(TextPartGameObject, description, parrentMenu.textColor, TextPart.TextPartType.Description)).gameObject).name = "Description"; text = arg_Name; selectionColorHandler = new SelectionColorHandler(this); AddListener(sMenuManager.nodeEvent.OnSelected, selectionColorHandler.onSelected); AddListener(sMenuManager.nodeEvent.OnDeselected, selectionColorHandler.OnDeselected); AddListener(sMenuManager.nodeEvent.OnPressed, selectionColorHandler.OnPressed); AddListener(sMenuManager.nodeEvent.OnUnpressed, selectionColorHandler.OnUnpressed); parrentMenu.AddListener(sMenuManager.menuEvent.OnClosed, selectionColorHandler.onClosed); } public sMenuNode Update() { if (selected) { eventMap[sMenuManager.nodeEvent.WhileSelected].Invoke(); parrentMenu.selectedNode = this; } else { eventMap[sMenuManager.nodeEvent.WhileDeselected].Invoke(); } if (!pressed) { eventMap[sMenuManager.nodeEvent.WhileUnpressed].Invoke(); } return this; } public Vector3 GetRelativePosition() { //IL_0006: 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_0025: 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_0044: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_006b: 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) Vector3 val = Vector3.Scale(new Vector3(rect.anchoredPosition.x, rect.anchoredPosition.y, 0f), ((Component)parrentMenu.getCanvas()).transform.localScale); Vector3 val2 = parrentMenu.gameObject.transform.TransformPoint(val); return ((Component)sMenuManager.mainCamera).transform.position - val2; } public sMenuNode SetPosition(float x, float y) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) SetPosition(new Vector2(x, y)); return this; } public sMenuNode SetPosition(Vector2 pos) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) rect.anchoredPosition = pos; return this; } public sMenuNode SetSize(float scale) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) return this.SetSize(new Vector3(scale, scale, scale)); } public sMenuNode SetSize(float x, float y) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) this.SetSize(new Vector2(x, y)); return this; } public sMenuNode SetSize(Vector2 scale) { //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) //IL_0013: 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) this.SetSize(new Vector3(scale.x, scale.y, ((Transform)rect).localScale.z)); return this; } public sMenuNode SetSize(float x, float y, float z) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) this.SetSize(new Vector3(x, y, z)); return this; } public sMenuNode SetSize(Vector3 scale) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((Transform)rect).localScale = scale; return this; } public sMenuNode SetCloseMenuOnPress(bool close) { closeOnPress = close; return this; } public sMenuNode FaceCamera() { //IL_000b: 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_0029: 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) Quaternion rotation = Quaternion.LookRotation(gameObject.transform.position - ((Component)sMenuManager.mainCamera).transform.position); setRotation(rotation); return this; } public sMenuNode setRotation(Quaternion rot) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) gameObject.transform.rotation = rot; return this; } public sMenuNode Select() { if (selected) { return this; } selected = true; SetSize(sMenuManager.selectedNodeSizeMultiplier); eventMap[sMenuManager.nodeEvent.OnSelected].Invoke(); parrentMenu.OnSelected.Invoke(); return this; } public sMenuNode Deselect() { if (!selected) { return this; } selected = false; SetSize(1f); eventMap[sMenuManager.nodeEvent.OnDeselected].Invoke(); parrentMenu.OnDeselected.Invoke(); return this; } public sMenuNode Pressing() { frameLastPressedAt = Time.frameCount; timeLastPressedAt = Time.time; eventMap[sMenuManager.nodeEvent.WhilePressed].Invoke(); if (Time.time - timeFirstPressedAt > holdThreshold) { if (held) { if (selected) { eventMap[sMenuManager.nodeEvent.WhileHeldSelected].Invoke(); } else { eventMap[sMenuManager.nodeEvent.WhileHeld].Invoke(); } } else { held = true; if (selected) { eventMap[sMenuManager.nodeEvent.OnHeldImmediateSelected].Invoke(); } eventMap[sMenuManager.nodeEvent.OnHeldImmediate].Invoke(); } } return this; } public sMenuNode Press() { frameFirstPressedAt = Time.frameCount; timeFirstPressedAt = Time.time; pressed = true; eventMap[sMenuManager.nodeEvent.OnPressed].Invoke(); if (closeOnPress) { sMenuManager.CloseAllMenus(); return this; } return this; } public sMenuNode Unpress() { if (pressed) { eventMap[sMenuManager.nodeEvent.OnUnpressed].Invoke(); if (held) { eventMap[sMenuManager.nodeEvent.OnHeld].Invoke(); } if (selected) { eventMap[sMenuManager.nodeEvent.OnUnpressedSelected].Invoke(); } if (held && selected) { eventMap[sMenuManager.nodeEvent.OnHeldSelected].Invoke(); } if (Time.time - timeFirstPressedAt < holdThreshold) { eventMap[sMenuManager.nodeEvent.OnTapped].Invoke(); if (Time.time - lastTapTime <= doubleTapThreshold) { eventMap[sMenuManager.nodeEvent.OnDoubleTapped].Invoke(); } else { zUpdater.InvokeStatic(new FlexibleMethodDefinition(new Action(InvokeTappedExclusive)), doubleTapThreshold - Time.deltaTime / 2f); } lastTapTime = Time.time; } } held = false; pressed = false; return this; } private void InvokeTappedExclusive() { if (Time.time - lastTapTime >= doubleTapThreshold - Time.deltaTime && !pressed) { eventMap[sMenuManager.nodeEvent.OnTappedExclusive].Invoke(); } } public sMenuNode AddListener(sMenuManager.nodeEvent arg_event, Action arg_method) { return AddListener(arg_event, (FlexibleMethodDefinition)arg_method); } public sMenuNode AddListener(sMenuManager.nodeEvent arg_event, Delegate method, params object[] args) { FlexibleMethodDefinition arg_method = new FlexibleMethodDefinition(method, args); return AddListener(arg_event, arg_method); } public sMenuNode AddListener(sMenuManager.nodeEvent arg_event, FlexibleMethodDefinition arg_method) { if (eventMap.TryGetValue(arg_event, out var value)) { value.Listen(arg_method); } return this; } public sMenuNode RemoveListener(sMenuManager.nodeEvent arg_event, Action arg_method) { if (eventMap.TryGetValue(arg_event, out var value)) { value.Unlisten(arg_method); } return this; } public sMenuNode RemoveListener(sMenuManager.nodeEvent arg_event) { if (eventMap.TryGetValue(arg_event, out var value)) { value.ClearListeners(); } return this; } public sMenuNode RemoveListener(sMenuManager.nodeEvent arg_event, FlexibleMethodDefinition arg_method) { if (eventMap.TryGetValue(arg_event, out var value)) { value.Unlisten(arg_method); } return this; } public sMenuNode ClearListeners(sMenuManager.nodeEvent arg_event) { if (eventMap.TryGetValue(arg_event, out var value)) { value.ClearListeners(); } return this; } public sMenuNode SetTitle(string arg_Title) { title = arg_Title ?? string.Empty; return this; } public sMenuNode SetSubtitle(string arg_Subtitle) { subtitle = arg_Subtitle ?? string.Empty; return this; } public sMenuNode SetDescription(string arg_Description) { description = arg_Description ?? string.Empty; return this; } public sMenuNode SetText(string arg_Text) { text = arg_Text ?? string.Empty; return this; } public sMenuNode SetPrefix(string arg_Prefix) { prefix = arg_Prefix ?? string.Empty; return this; } public sMenuNode SetSuffix(string arg_Suffix) { suffix = arg_Suffix ?? string.Empty; return this; } public sMenuNode SetColor(Color arg_Color) { //IL_0001: 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_001f: 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_0040: 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) //IL_0064: 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) color = arg_Color; foreach (TextPart textPart in GetTextParts()) { Color val = arg_Color; val.r += ColorOffset.r; val.g += ColorOffset.g; val.b += ColorOffset.b; val.a = arg_Color.a; textPart.SetColor(val); } return this; } public sMenuNode AddHoverText(sMenuPannel.Side side, string[] textList) { foreach (string text in textList) { AddHoverText(side, text); } return this; } public sMenuNode AddHoverText(sMenuPannel.Side side, string text) { sMenuPannel pannel = parrentMenu.AddPannel(side); string key = ((Object)gameObject).GetInstanceID().ToString(); pannel.addLine(text, key); pannel.SetLineVisible(visible: false, text, key); if (!hasHoverText) { AddListener(sMenuManager.nodeEvent.OnSelected, delegate { pannel.SetKeyVisible(visible: true, key); }); AddListener(sMenuManager.nodeEvent.OnDeselected, delegate { pannel.SetKeyVisible(visible: false, key); }); hasHoverText = true; } return this; } public List<TextPart> GetTextParts(TextPart.TextPartType types = TextPart.TextPartType.All) { return (from f in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where f.FieldType == typeof(TextPart) select f.GetValue(this) as TextPart into tp where tp != null && (types & tp.type) != 0 select tp).ToList(); } private void UpdateTitle() { if (titlePart != null) { titlePart.SetText(title); } } private void UpdateSubtitle() { if (subtitlePart != null) { subtitlePart.SetText(subtitle); } } private void UpdateDescription() { if (descriptionPart != null) { descriptionPart.SetText(description); } } private void UpdateText() { if (fullTextPart != null) { fullTextPart.SetText(fullText); } } } public class sMenuPannel { public enum Side { left, right, top, bottom } public Side side; public sMenu parrentMenu; public GameObject gameObject; public RectTransform rect; public Color color; public Dictionary<string, List<TextPart>> lines = new Dictionary<string, List<TextPart>>(); public sMenuPannel(Side side, sMenu parrentMenu) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //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_00ad: 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) this.side = side; gameObject = new GameObject($"zMenuPannel {side}"); gameObject.transform.SetParent(((Component)parrentMenu.getCanvas()).transform, false); this.parrentMenu = parrentMenu; color = parrentMenu.getTextColor(); rect = gameObject.GetComponent<RectTransform>(); if ((Object)(object)rect == (Object)null) { rect = gameObject.AddComponent<RectTransform>(); } ((Transform)rect).localScale = Vector3.one; rect.sizeDelta = new Vector2(300f, 0f); VerticalLayoutGroup obj = gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 2f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = side == Side.top || side == Side.bottom; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ContentSizeFitter obj2 = gameObject.AddComponent<ContentSizeFitter>(); obj2.verticalFit = (FitMode)2; obj2.horizontalFit = (FitMode)2; UpdatePosition(); } public sMenuPannel UpdatePosition(float margin = 0f) { //IL_0006: 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_000c: 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_00ac: 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_00e0: 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_005e: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) Rect nodeBounds = parrentMenu.GetNodeBounds(); Vector2 zero = Vector2.zero; switch (side) { case Side.right: rect.anchorMax = new Vector2(0f, 0.5f); rect.anchorMin = new Vector2(0f, 0.5f); rect.pivot = new Vector2(0f, 0.5f); ((Vector2)(ref zero))..ctor(((Rect)(ref nodeBounds)).xMax + margin, 0f); break; case Side.left: rect.anchorMax = new Vector2(1f, 0.5f); rect.anchorMin = new Vector2(1f, 0.5f); rect.pivot = new Vector2(1f, 0.5f); ((Vector2)(ref zero))..ctor(((Rect)(ref nodeBounds)).xMin - margin, 0f); break; case Side.top: rect.anchorMax = new Vector2(0.5f, 0f); rect.anchorMin = new Vector2(0.5f, 0f); rect.pivot = new Vector2(0.5f, 0f); ((Vector2)(ref zero))..ctor(0f, ((Rect)(ref nodeBounds)).yMax + margin); break; case Side.bottom: rect.anchorMax = new Vector2(0.5f, 1f); rect.anchorMin = new Vector2(0.5f, 1f); rect.pivot = new Vector2(0.5f, 1f); ((Vector2)(ref zero))..ctor(0f, ((Rect)(ref nodeBounds)).yMin - margin); break; } gameObject.transform.localPosition = Vector2.op_Implicit(zero); FaceCamera(); return this; } public TextPart addLine(string lineText, string key = "Default") { //IL_000d: Unknown result type (might be due to invalid IL or missing references) TextPart textPart = new TextPart(gameObject, lineText, parrentMenu.textColor, TextPart.TextPartType.Pannel); textPart.gameObject.transform.SetParent(gameObject.transform, false); if (!lines.ContainsKey(key)) { lines[key] = new List<TextPart>(); } lines[key].Add(textPart); return textPart; } public sMenuPannel FaceCamera() { //IL_000b: 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_0029: 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) Quaternion rotation = Quaternion.LookRotation(gameObject.transform.position - ((Component)sMenuManager.mainCamera).transform.position); setRotation(rotation); return this; } public sMenuPannel setRotation(Quaternion rot) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) gameObject.transform.rotation = rot; return this; } public TextPart GetLine(string lineText, string key) { TextPart result = null; foreach (TextPart item in lines[key]) { if (item.text.Contains(lineText)) { result = item; break; } } return result; } public sMenuPannel SetLineVisible(bool visible, string line, string key = "") { TextPart textPart = null; if (key == "") { foreach (string key2 in lines.Keys) { textPart = GetLine(line, key2); if (textPart != null) { break; } } } else if (lines.ContainsKey(key)) { textPart = GetLine(line, key); } textPart.gameObject.SetActive(visible); return this; } public sMenuPannel SetKeyVisible(bool visible, string key) { if (!lines.ContainsKey(key)) { return this; } foreach (TextPart item in lines[key]) { item.gameObject.SetActive(visible); } return this; } public bool IsLineVisible(string line, string key = "") { TextPart line2 = GetLine(line, key); if (line2 != null) { return line2.gameObject.activeInHierarchy; } return false; } public bool IsKeyVisible(string key) { if (!lines.ContainsKey(key)) { return false; } int num = 0; foreach (TextPart item in lines[key]) { num = ((!item.gameObject.activeInHierarchy) ? (num - 1) : (num + 1)); } return num > 0; } public sMenuPannel ToggleLineVisiblity(string line, string key = "") { if (!lines.ContainsKey(key)) { return this; } bool flag = IsLineVisible(line, key); SetLineVisible(!flag, line, key); return this; } public sMenuPannel ToggleKeyVisiblity(string key) { if (!lines.ContainsKey(key)) { return this; } bool flag = IsKeyVisible(key); SetKeyVisible(!flag, key); return this; } } public class TextPart { [Flags] public enum TextPartType { none = 0, Main = 1, Title = 2, Subtitle = 4, Description = 8, Pannel = 0x10, Default = 0x20, All = 0x3F } public TextPartType type; private string _text; private Color _textColor; private Color _colorOffset; private TextMeshPro textMesh; public string text { get { return _text; } set { _text = value; ((TMP_Text)textMesh).text = value; } } public Color textColor { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _textColor; } set { //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) //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_0017: Unknown result type (might be due to invalid IL or missing references) Color val = _textColor; _textColor = value; if (val != value) { I_SetColor(_textColor); } } } public Color ColorOffset { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _colorOffset; } set { //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) //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_0017: Unknown result type (might be due to invalid IL or missing references) Color colorOffset = _colorOffset; _colorOffset = value; if (colorOffset != value) { I_SetColor(_textColor); } } } public GameObject gameObject { get; private set; } public RectTransform rect { get; private set; } public TextPart(GameObject parent, string arg_Text, Color color, TextPartType type) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0024: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) this.type = type; gameObject = new GameObject(); gameObject.transform.position = Vector3.zero; gameObject.transform.rotation = Quaternion.identity; gameObject.transform.localScale = Vector3.one; gameObject.layer = 0; gameObject.tag = "Untagged"; gameObject.SetActive(true); gameObject.transform.SetParent(parent.transform, false); ((Object)gameObject).name = "TextPart " + arg_Text; rect = gameObject.AddComponent<RectTransform>(); rect.anchoredPosition = Vector2.zero; ((Transform)rect).localScale = Vector3.one; rect.sizeDelta = new Vector2(300f, 0f); textMesh = gameObject.AddComponent<TextMeshPro>(); ((TMP_Text)textMesh).enableAutoSizing = false; ((TMP_Text)textMesh).fontSize = sMenuManager.defaultFontSize; ((TMP_Text)textMesh).alignment = (TextAlignmentOptions)514; ((Graphic)textMesh).color = color; text = arg_Text; ContentSizeFitter obj = gameObject.AddComponent<ContentSizeFitter>(); obj.verticalFit = (FitMode)2; obj.horizontalFit = (FitMode)2; } public TextPart SetText(string newText) { text = newText; return this; } public TextPart SetPosition(Vector2 pos) { //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) SetPosition(pos.x, pos.y); return this; } public TextPart SetPosition(float x, float y) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) rect.anchoredPosition = new Vector2(x, y); return this; } public TextPart SetScale(float scale) { SetScale(scale, scale, 1f); return this; } public TextPart SetScale(Vector2 scale) { //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) SetScale(scale.x, scale.y, 1f); return this; } public TextPart SetScale(Vector3 scale) { //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) //IL_000d: Unknown result type (might be due to invalid IL or missing references) SetScale(scale.x, scale.y, scale.z); return this; } public TextPart SetScale(float x, float y) { SetScale(x, y, 1f); return this; } public TextPart SetScale(float x, float y, float z) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) ((Transform)rect).localScale = new Vector3(x, y, z); return this; } private TextPart I_SetColor(Color color) { //IL_0007: 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) ((Graphic)textMesh).color = textColor + ColorOffset; return this; } public TextPart SetColor(Color color) { //IL_0001: 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_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) textColor = color; ((Graphic)textMesh).color = textColor + ColorOffset; return this; } public Color GetColor() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return textColor; } } private string name; private sMenu _parrentMenu; internal int frameOpenedAt = Time.frameCount; internal float timeOpenedAt = Time.time; public GameObject gameObject; private Canvas canvas; public Vector3 RelativePosition = Vector3.zero; private Dictionary<sMenuManager.menuEvent, FlexibleEvent> eventMap; public Dictionary<string, List<sMenuNode>> catagories = new Dictionary<string, List<sMenuNode>>(); private int catagoryIndex; private FlexibleEvent OnOpened = new FlexibleEvent(); private FlexibleEvent WhileOpened = new FlexibleEvent(); private FlexibleEvent OnClosed = new FlexibleEvent(); private FlexibleEvent WhileClosed = new FlexibleEvent(); private FlexibleEvent OnSelected = new FlexibleEvent(); private FlexibleEvent WhileSelected = new FlexibleEvent(); private FlexibleEvent OnDeselected = new FlexibleEvent(); private FlexibleEvent WhileDeselected = new FlexibleEvent(); private FlexibleEvent OnCatagoryChanged = new FlexibleEvent(); private int pannelPositionWorkaround; private Vector3 canvasScale = new Vector3(0.003f, 0.003f, 0.003f); public float radius; public float rotationalOffset; private Color textColor = sMenuManager.defaultColor; private sMenuNode selectedNode; private RectTransform rect; private Dictionary<sMenuPannel.Side, sMenuPannel> pannels = new Dictionary<sMenuPannel.Side, sMenuPannel>(); public IEnumerable<sMenuNode> allNodes { get { if (centerNode == null) { return nodes; } return new sMenuNode[1] { centerNode }.Concat(nodes.Where((sMenuNode n) => n != centerNode)); } } public OrderedSet<sMenuNode> nodes { get; private set; } = new OrderedSet<sMenuNode>(); public OrderedSet<sMenuNode> disabledNodes { get; private set; } = new OrderedSet<sMenuNode>(); public sMenuNode centerNode { get; private set; } public sMenu parrentMenu { get { return _parrentMenu; } private set { _parrentMenu = value; if (value != null) { centerNode.ClearListeners(sMenuManager.nodeEvent.OnUnpressedSelected); centerNode.AddListener(sMenuManager.nodeEvent.OnUnpressedSelected, _parrentMenu.Open); } } } public List<sMenuNode> currentCatagory => catagories[currentCatagoryName]; public string currentCatagoryName => catagories.Keys.ToArray().ElementAt(catagoryIndex); public sMenu(string arg_Name, sMenu arg_ParrentMenu = null) { //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_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_00c0: 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_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown eventMap = new Dictionary<sMenuManager.menuEvent, FlexibleEvent> { { sMenuManager.menuEvent.OnOpened, OnOpened }, { sMenuManager.menuEvent.WhileOpened, WhileOpened }, { sMenuManager.menuEvent.OnClosed, OnClosed }, { sMenuManager.menuEvent.WhileClosed, WhileClosed }, { sMenuManager.menuEvent.OnSelected, OnSelected }, { sMenuManager.menuEvent.WhileSelected, WhileSelected }, { sMenuManager.menuEvent.OnDeselected, OnDeselected }, { sMenuManager.menuEvent.WhileDeselected, WhileDeselected }, { sMenuManager.menuEvent.OnCatagoryChanged, OnCatagoryChanged } }; radius = sMenuManager.defaultRadius; name = arg_Name; gameObject = new GameObject("sMenu " + name); gameObject.transform.SetParent(sMenuManager.menuParrent.transform); setupCanvas(); centerNode = new sMenuNode(arg_Callback: (arg_ParrentMenu == null) ? new FlexibleMethodDefinition(new Func<sMenu>(Close)) : new FlexibleMethodDefinition(new Action(arg_ParrentMenu.Open)), arg_Name: name, arg_parrentMenu: this).SetTitle((arg_ParrentMenu != null) ? arg_ParrentMenu.name : "Close"); parrentMenu = arg_ParrentMenu; Close(); } internal void UpdateCatagoryByScroll() { if (catagories.Count() == 0) { return; } float axis = Input.GetAxis("Mouse ScrollWheel"); int num = (int)Mathf.Sign(axis); if (axis != 0f) { catagoryIndex += num; if (catagoryIndex >= catagories.Count()) { catagoryIndex = 0; } if (catagoryIndex < 0) { catagoryIndex = catagories.Count() - 1; } SetCatagory(catagories.Keys.ElementAt(catagoryIndex)); } } public void UpdateCatagoryNodes() { if (catagoryIndex >= catagories.Count()) { return; } string text = catagories.Keys.ElementAt(catagoryIndex); centerNode.SetSubtitle("<color=#00CC8466>[ </color>" + text + "<color=#00CC8466> ]</color>"); if (text.ToLower() == "all") { foreach (sMenuNode node in nodes) { EnableNode(node); } return; } foreach (sMenuNode node2 in nodes) { if (catagories[text].Contains(node2)) { EnableNode(node2); } else { DisableNode(node2); } } } public void SetCatagory(string catagory) { if (!catagories.ContainsKey(catagory)) { return; } centerNode.SetSubtitle("<color=#00CC8466>[ </color>" + catagory + "<color=#00CC8466> ]</color>"); if (catagory.ToLower() == "all") { foreach (sMenuNode node in nodes) { EnableNode(node); } return; } foreach (sMenuNode node2 in nodes) { if (catagories[catagory].Contains(node2)) { EnableNode(node2); } else { DisableNode(node2); } } catagoryIndex = catagories.Keys.ToList().IndexOf(catagory); UpdatePannelPositions(); OnCatagoryChanged.Invoke(); } public void AddCatagory(string catagory) { if (!catagories.ContainsKey(catagory)) { catagories[catagory] = new List<sMenuNode>(); } } public void AddNodeToCatagory(string catagory, sMenuNode node) { if (node != null) { if (!catagories.ContainsKey(catagory)) { AddCatagory(catagory); } catagories[catagory].Add(node); } } public void AddNodeToCatagory(string catagory, string nodeName) { sMenuNode node = GetNode(nodeName); if (node != null) { AddNodeToCatagory(catagory, node); } } public void UpdatePosition() { //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_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)sMenuManager.mainCamera).transform.position - RelativePosition; setPosition(position); } public void Update() { if (gameObject.activeInHierarchy) { WhileOpened.Invoke(); } else { WhileClosed.Invoke(); } selectedNode = null; foreach (sMenuNode item in allNodes.Where((sMenuNode n) => n.gameObject.activeInHierarchy).ToList()) { item.Update(); } if (selectedNode != null) { WhileSelected.Invoke(); } else { WhileDeselected.Invoke(); } if (pannelPositionWorkaround < 2) { _UpdatePannelPositions(); } } public void Lateupdate() { UpdatePosition(); FaceCamera(); } public void PreRender() { UpdatePosition(); FaceCamera(); } public sMenu Close() { setVisiblity(visible: false); if (sMenuManager.currentMenu == this) { sMenuManager.currentMenu = null; } OnClosed.Invoke(); return this; } public void Open() { //IL_0056: 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_006b: 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) timeOpenedAt = Time.time; frameOpenedAt = Time.frameCount; if (parrentMenu == null) { if (RelativePosition == Vector3.zero) { MoveInfrontOfCamera(); } } else { sMenuNode node = parrentMenu.GetNode(name); SetRelativePosition(((Component)sMenuManager.mainCamera).transform.position - node.gameObject.transform.position); } FaceCamera(); setVisiblity(visible: true); ArrangeNodes(); sMenuManager.previousMenu = sMenuManager.currentMenu; sMenuManager.currentMenu = this; if (sMenuManager.previousMenu != null && sMenuManager.previousMenu != this) { sMenuManager.previousMenu.Close(); } OnOpened.Invoke(); } public sMenuPannel AddPannel(sMenuPannel.Side side, string initialText = "") { if (pannels.ContainsKey(side)) { if (initialText != "") { pannels[side].addLine(initialText); } return pannels[side]; } sMenuPannel sMenuPannel = new sMenuPannel(side, this); if (initialText != "") { sMenuPannel.addLine(initialText); } pannels[side] = sMenuPannel; return sMenuPannel; } public sMenu SetRelativePosition(float x, float y, float z) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) return SetRelativePosition(new Vector3(x, y, z)); } public sMenu SetRelativePosition(Vector3 relativePosition) { //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_0012: 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) RelativePosition = relativePosition; return setPosition(((Component)sMenuManager.mainCamera).transform.position - RelativePosition); } public sMenu ResetRelativePosition(bool setPos = true) { //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_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) //IL_0031: Unknown result type (might be due to invalid IL or missing references) RelativePosition = Vector3.zero; if (setPos && (Object)(object)sMenuManager.mainCamera != (Object)null) { return setPosition(((Component)sMenuManager.mainCamera).transform.position - RelativePosition); } return this; } private void AddDebugVisuals() { //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_003f: 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_0069: 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_007f: 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_0098: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)canvas == (Object)null) { Debug.LogWarning(Object.op_Implicit("zMenu: Tried to add debug visuals, but canvas is null!")); return; } GameObject val = new GameObject("DebugBackground"); val.transform.SetParent(((Component)canvas).transform, false); ((Graphic)val.AddComponent<Image>()).color = new Color(0.5f, 0.5f, 0.5f, 0.5f); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; GameObject val2 = new GameObject("DebugText"); val2.transform.SetParent(((Component)canvas).transform, false); TextMeshPro obj = val2.AddComponent<TextMeshPro>(); ((TMP_Text)obj).text = "Hello from " + name; ((TMP_Text)obj).fontSize = 24f; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((Graphic)obj).color = Color.white; RectTransform component2 = ((Component)obj).GetComponent<RectTransform>(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; } private void setupCanvas() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_007a: 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_00aa: 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) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)canvas)) { GameObject val = new GameObject("Canvas"); val.transform.SetParent(gameObject.transform, false); canvas = val.AddComponent<Canvas>(); canvas.renderMode = (RenderMode)2; canvas.worldCamera = Camera.main; val.AddComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f; rect = val.GetComponent<RectTransform>(); ((Transform)rect).localPosition = Vector3.zero; ((Transform)rect).localScale = canvasScale; gameObject.transform.position = ((Component)sMenuManager.mainCamera).transform.position + ((Component)sMenuManager.mainCamera).transform.forward * 1f; gameObject.transform.rotation = Quaternion.LookRotation(gameObject.transform.position - ((Component)sMenuManager.mainCamera).transform.position); } } internal void Setsize(float scale) { //IL_0007: 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) ((Transform)rect).localScale = canvasScale * scale; } public sMenu ArrangeNodes() { List<sMenuNode> list = nodes.Where((sMenuNode n) => n.gameObject.activeInHierarchy).ToList(); float num = 0f; if (rotationalOffset == 0f && list.Count() == 4) { num = 45f; } if (rotationalOffset == 0f && list.Count() == 2) { num = 90f; } float num2 = (rotationalOffset + num) * ((float)Math.PI / 180f); int count = list.Count; if (count != 0) { for (int num3 = 0; num3 < count; num3++) { float num4 = (float)Math.PI * 2f / (float)count * (float)num3 - (float)Math.PI / 2f + num2; float x = radius * Mathf.Cos(num4); float y = (0f - radius) * Mathf.Sin(num4); list[num3].SetPosition(x, y); } } UpdatePannelPositions(); return this; } public sMenu UpdatePannelPositions() { pannelPositionWorkaround = 0; return _UpdatePannelPositions(); } private sMenu _UpdatePannelPositions() { pannelPositionWorkaround++; foreach (sMenuPannel value in pannels.Values) { value.UpdatePosition(); } return this; } public sMenu MoveInfrontOfCamera() { //IL_000a: 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_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_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_003f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)sMenuManager.mainCamera).transform.position + ((Component)sMenuManager.mainCamera).transform.forward * 1f; return SetRelativePosition(((Component)sMenuManager.mainCamera).transform.position - val); } public sMenu FaceCamera(bool menuOnly = false) { //IL_000b: 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_0029: 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) Quaternion rotation = Quaternion.LookRotation(gameObject.transform.position - ((Component)sMenuManager.mainCamera).transform.position); setRotation(rotation); if (!menuOnly) { foreach (sMenuNode allNode in allNodes) { allNode.FaceCamera(); } } return this; } public sMenu setPosition(float x, float y, float z) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) return setPosition(new Vector3(x, y, z)); } public sMenu setPosition(Vector3 pos) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) gameObject.transform.position = pos; return this; } public sMenu setLocalPosition(float x, float y, float z) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) return setLocalPosition(new Vector3(x, y, z)); } public sMenu setLocalPosition(Vector3 pos) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) gameObject.transform.localPosition = pos; return this; } public sMenu setRotation(Quaternion rot) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) gameObject.transform.rotation = rot; return this; } public sMenu AddListener(sMenuManager.menuEvent arg_event, Action arg_method) { return AddListener(arg_event, (FlexibleMethodDefinition)arg_method); } public sMenu AddListener(sMenuManager.menuEvent arg_event, Delegate method, params object[] args) { FlexibleMethodDefinition arg_method = new FlexibleMethodDefinition(method, args); return AddListener(arg_event, arg_method); } public sMenu AddListener(sMenuManager.menuEvent arg_event, FlexibleMethodDefinition arg_method) { if (eventMap.TryGetValue(arg_event, out var value)) { value.Listen(arg_method); } return this; } public sMenu RemoveListener(sMenuManager.menuEvent arg_event, Action arg_method) { if (eventMap.TryGetValue(arg_event, out var value)) { value.Unlisten(arg_method); } return this; } public sMenu RemoveListener(sMenuManager.menuEvent arg_event) { if (eventMap.TryGetValue(arg_event, out var value)) { value.ClearListeners(); } return this; } public sMenu RemoveListener(sMenuManager.menuEvent arg_event, FlexibleMethodDefinition arg_method) { if (eventMap.TryGetValue(arg_event, out var value)) { value.Unlisten(arg_method); } return this; } public sMenu ClearListeners(sMenuManager.menuEvent arg_event) { if (eventMap.TryGetValue(arg_event, out var value)) { value.ClearListeners(); } return this; } public void DisableNode(sMenuNode node) { if (!disabledNodes.Contains(node)) { disabledNodes.Add(node); node.gameObject.SetActive(false); ArrangeNodes(); } } public void DisableNode(sMenu menu) { sMenuNode sMenuNode = nodes.FirstOrDefault((sMenuNode n) => n.text == menu.centerNode.text); if (sMenuNode != null) { DisableNode(sMenuNode); } } public void DisableNode(string nodeText) { sMenuNode sMenuNode = nodes.FirstOrDefault((sMenuNode n) => n.text == nodeText); if (sMenuNode != null) { DisableNode(sMenuNode); } } public void EnableNode(sMenuNode node) {