Decompiled source of ItemShareFix v1.2.0

ItemShareFix/ItemShareFix.Core.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ItemShareFix.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("ItemShareFix.Core")]
[assembly: AssemblyTitle("ItemShareFix.Core")]
[assembly: AssemblyVersion("1.2.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 ItemShareFix.Core
{
	public sealed class AuthoritativeEligibilityMirror<TOwner, TOption> where TOwner : class where TOption : class
	{
		private sealed class Entry
		{
			public uint Request;

			public double NextRequest;

			public bool HasSnapshot;

			public WeakReference<TOwner> Owner { get; }

			public HashSet<TOption> Allowed { get; } = new HashSet<TOption>();

			public HashSet<uint> Collectors { get; } = new HashSet<uint>();

			public Entry(TOwner owner)
			{
				Owner = new WeakReference<TOwner>(owner);
			}
		}

		private readonly Dictionary<int, Entry> _entries = new Dictionary<int, Entry>();

		private readonly List<int> _stale = new List<int>();

		private uint _sequence;

		public int Count => _entries.Count;

		public uint Request(int id, TOwner owner, double now)
		{
			if (!_entries.TryGetValue(id, out Entry value) || !Matches(value, owner))
			{
				value = (_entries[id] = new Entry(owner));
			}
			if (now < value.NextRequest)
			{
				return 0u;
			}
			value.NextRequest = now + 1.0;
			if (value.Request != 0)
			{
				return value.Request;
			}
			if (++_sequence == 0)
			{
				_sequence++;
			}
			return value.Request = _sequence;
		}

		public bool Apply(int id, TOwner owner, uint request, IEnumerable<TOption> allowed, IEnumerable<uint>? collectors = null)
		{
			if (request == 0 || !_entries.TryGetValue(id, out Entry value) || !Matches(value, owner) || value.Request != request)
			{
				return false;
			}
			value.Allowed.Clear();
			foreach (TOption item in allowed)
			{
				value.Allowed.Add(item);
			}
			value.Collectors.Clear();
			if (collectors != null)
			{
				foreach (uint collector in collectors)
				{
					if (collector != 0)
					{
						value.Collectors.Add(collector);
					}
				}
			}
			value.HasSnapshot = true;
			value.Request = 0u;
			return true;
		}

		public bool Contains(int id, TOwner owner, TOption option)
		{
			if (_entries.TryGetValue(id, out Entry value) && Matches(value, owner))
			{
				return value.Allowed.Contains(option);
			}
			return false;
		}

		public bool HasRetainedOptions(int id, TOwner owner)
		{
			if (_entries.TryGetValue(id, out Entry value) && Matches(value, owner) && value.HasSnapshot)
			{
				return value.Allowed.Count > 0;
			}
			return false;
		}

		public bool TryCollected(int id, TOwner owner, uint master, out bool collected)
		{
			collected = false;
			if (master == 0 || !_entries.TryGetValue(id, out Entry value) || !Matches(value, owner) || !value.HasSnapshot)
			{
				return false;
			}
			collected = value.Collectors.Contains(master);
			return true;
		}

		private static bool Matches(Entry entry, TOwner owner)
		{
			if (entry.Owner.TryGetTarget(out var target))
			{
				return target == owner;
			}
			return false;
		}

		public void Prune(Func<TOwner, bool> live)
		{
			_stale.Clear();
			foreach (KeyValuePair<int, Entry> entry in _entries)
			{
				if (!entry.Value.Owner.TryGetTarget(out var target) || !live(target))
				{
					_stale.Add(entry.Key);
				}
			}
			foreach (int item in _stale)
			{
				_entries.Remove(item);
			}
		}

		public void Clear()
		{
			_entries.Clear();
			_stale.Clear();
		}
	}
	public static class BlockingModalLifecyclePolicy
	{
		public const string PauseScreenControllerTypeName = "RoR2.UI.PauseScreenController";

		public const string SimpleDialogBoxTypeName = "RoR2.UI.SimpleDialogBox";

		public const string PickupPickerPanelTypeName = "RoR2.UI.PickupPickerPanel";

		public static bool IsKnownBlockingModalTypeName(string? typeName)
		{
			if (!(typeName == "RoR2.UI.PauseScreenController") && !(typeName == "RoR2.UI.SimpleDialogBox"))
			{
				return typeName == "RoR2.UI.PickupPickerPanel";
			}
			return true;
		}

		public static bool ShouldSeedObservedCandidate(bool knownBlockingType, bool sceneObjectValid)
		{
			return knownBlockingType && sceneObjectValid;
		}

		public static bool ShouldAddObservedInstance(bool instanceAlreadyCached)
		{
			return !instanceAlreadyCached;
		}

		public static bool LifecycleSeedRequiresGlobalDiscovery(bool observedCandidateCached)
		{
			return !observedCandidateCached;
		}

		public static bool SuppressionStateChanged(bool previousSuppressed, bool currentSuppressed)
		{
			return previousSuppressed != currentSuppressed;
		}

		public static bool PreserveRareFallbackCadence(float fallbackSeconds)
		{
			return fallbackSeconds >= 5f;
		}
	}
	public sealed class ClaimLedger
	{
		private readonly Dictionary<ClaimKey, ClaimRecord> _records = new Dictionary<ClaimKey, ClaimRecord>();

		private readonly Dictionary<HistoricalClaimKey, HistoricalClaimRecord> _history = new Dictionary<HistoricalClaimKey, HistoricalClaimRecord>();

		public IReadOnlyCollection<ClaimRecord> Records => _records.Values;

		public IReadOnlyCollection<HistoricalClaimRecord> HistoricalRecords => _history.Values;

		public ClaimRecord Ensure(SharedPickupKey pickup, ParticipantKey participant, ParticipantState state, int stage)
		{
			if (!TryEnsure(pickup, participant, state, stage, out ClaimRecord record))
			{
				throw new InvalidOperationException("Historical pickup barrier rejected participant generation: " + pickup.ToString() + "/" + participant);
			}
			return record;
		}

		public bool TryEnsure(SharedPickupKey pickup, ParticipantKey participant, ParticipantState state, int stage, out ClaimRecord record)
		{
			ClaimKey key = new ClaimKey(pickup, participant);
			if (_records.TryGetValue(key, out ClaimRecord value))
			{
				record = value;
				return true;
			}
			if (IsHistoricallyBlocked(pickup, participant.StableUser))
			{
				record = null;
				return false;
			}
			ClaimState claimState = ((state == ParticipantState.FullyDead) ? ClaimState.Deferred : ClaimState.Pending);
			if (state == ParticipantState.Disconnected)
			{
				claimState = ClaimState.CancelledDisconnected;
			}
			ClaimRecord claimRecord = new ClaimRecord(key, claimState, stage);
			if (claimState == ClaimState.CancelledDisconnected)
			{
				claimRecord.TerminalStage = stage;
				SetHistory(pickup, participant.StableUser, HistoricalClaimState.CancelledDisconnected, stage);
			}
			_records.Add(key, claimRecord);
			record = claimRecord;
			return true;
		}

		public bool TryGet(SharedPickupKey pickup, ParticipantKey participant, out ClaimRecord record)
		{
			return _records.TryGetValue(new ClaimKey(pickup, participant), out record);
		}

		public bool IsHistoricallyBlocked(SharedPickupKey pickup, StableUserKey stableUser)
		{
			return _history.ContainsKey(new HistoricalClaimKey(pickup, stableUser));
		}

		public bool TryGetHistorical(SharedPickupKey pickup, StableUserKey stableUser, out HistoricalClaimRecord record)
		{
			return _history.TryGetValue(new HistoricalClaimKey(pickup, stableUser), out record);
		}

		public IReadOnlyList<HistoricalClaimRecord> HistoricalFor(StableUserKey stableUser)
		{
			return (from x in _history.Values
				where x.Key.StableUser.Equals(stableUser)
				orderby x.Key.Pickup.Value
				select x).ToArray();
		}

		public bool MarkCollected(SharedPickupKey pickup, ParticipantKey participant, int stage)
		{
			if (!TryGet(pickup, participant, out ClaimRecord record))
			{
				return false;
			}
			if (record.State != ClaimState.Pending)
			{
				return false;
			}
			record.State = ClaimState.Collected;
			record.TerminalStage = stage;
			SetHistory(pickup, participant.StableUser, HistoricalClaimState.Collected, stage);
			return true;
		}

		public int TransitionParticipant(ParticipantKey participant, ParticipantState from, ParticipantState to, int stage)
		{
			int num = 0;
			ClaimRecord[] array = _records.Values.Where((ClaimRecord x) => x.Key.Participant.Equals(participant)).ToArray();
			foreach (ClaimRecord claimRecord in array)
			{
				switch (to)
				{
				case ParticipantState.Disconnected:
					if (claimRecord.State == ClaimState.Pending || claimRecord.State == ClaimState.Deferred)
					{
						claimRecord.State = ClaimState.CancelledDisconnected;
						claimRecord.TerminalStage = stage;
						SetHistory(claimRecord.Key.Pickup, participant.StableUser, HistoricalClaimState.CancelledDisconnected, stage);
						num++;
					}
					break;
				case ParticipantState.FullyDead:
					if (claimRecord.State == ClaimState.Pending)
					{
						claimRecord.State = ClaimState.Deferred;
						num++;
					}
					break;
				}
			}
			return num;
		}

		public bool MarkDeferredGranted(ClaimKey key, int stage)
		{
			if (!_records.TryGetValue(key, out ClaimRecord value))
			{
				return false;
			}
			if (value.State != ClaimState.Deferred)
			{
				return false;
			}
			value.State = ClaimState.GrantedDeferred;
			value.TerminalStage = stage;
			SetHistory(value.Key.Pickup, value.Key.Participant.StableUser, HistoricalClaimState.GrantedDeferred, stage);
			return true;
		}

		public IReadOnlyList<ClaimRecord> DeferredFor(ParticipantKey participant, int beforeStage)
		{
			return (from x in _records.Values
				where x.Key.Participant.Equals(participant) && x.State == ClaimState.Deferred && x.CreatedStage < beforeStage
				orderby x.CreatedStage, x.Key.Pickup.Value
				select x).ToArray();
		}

		public int TransferPickup(SharedPickupKey oldPickup, SharedPickupKey newPickup)
		{
			if (oldPickup.Equals(newPickup))
			{
				return 0;
			}
			ClaimRecord[] array = _records.Values.Where((ClaimRecord x) => x.Key.Pickup.Equals(oldPickup)).ToArray();
			HistoricalClaimRecord[] array2 = _history.Values.Where((HistoricalClaimRecord x) => x.Key.Pickup.Equals(oldPickup)).ToArray();
			ClaimRecord[] array3 = array;
			foreach (ClaimRecord claimRecord in array3)
			{
				ClaimKey key = new ClaimKey(newPickup, claimRecord.Key.Participant);
				if (_records.ContainsKey(key))
				{
					throw new InvalidOperationException("Transfer would create duplicate pickup/participant state: " + key);
				}
			}
			HistoricalClaimRecord[] array4 = array2;
			foreach (HistoricalClaimRecord historicalClaimRecord in array4)
			{
				HistoricalClaimKey key2 = new HistoricalClaimKey(newPickup, historicalClaimRecord.Key.StableUser);
				if (_history.TryGetValue(key2, out HistoricalClaimRecord value) && value.State != historicalClaimRecord.State)
				{
					throw new InvalidOperationException("Transfer would create conflicting historical pickup/stable-user state: " + key2);
				}
			}
			array3 = array;
			foreach (ClaimRecord claimRecord2 in array3)
			{
				ClaimKey key3 = claimRecord2.Key;
				ClaimKey key4 = new ClaimKey(newPickup, key3.Participant);
				_records.Remove(key3);
				claimRecord2.Key = key4;
				_records.Add(key4, claimRecord2);
			}
			array4 = array2;
			foreach (HistoricalClaimRecord historicalClaimRecord2 in array4)
			{
				HistoricalClaimKey key5 = historicalClaimRecord2.Key;
				HistoricalClaimKey key6 = new HistoricalClaimKey(newPickup, key5.StableUser);
				_history.Remove(key5);
				if (_history.TryGetValue(key6, out HistoricalClaimRecord value2))
				{
					if (historicalClaimRecord2.Stage > value2.Stage)
					{
						value2.Stage = historicalClaimRecord2.Stage;
					}
				}
				else
				{
					historicalClaimRecord2.Key = key6;
					_history.Add(key6, historicalClaimRecord2);
				}
			}
			return array.Length;
		}

		public int OnStageTransition(int newStage)
		{
			int num = 0;
			KeyValuePair<ClaimKey, ClaimRecord>[] array = _records.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<ClaimKey, ClaimRecord> keyValuePair = array[i];
				ClaimState state = keyValuePair.Value.State;
				if (state == ClaimState.Pending || state == ClaimState.Collected || state == ClaimState.CancelledDisconnected || state == ClaimState.GrantedDeferred)
				{
					_records.Remove(keyValuePair.Key);
					num++;
				}
			}
			_history.Clear();
			return num;
		}

		public int Clear()
		{
			int result = _records.Count + _history.Count;
			_records.Clear();
			_history.Clear();
			return result;
		}

		public int RemoveTerminalOlderThan(int stageExclusive)
		{
			int num = 0;
			KeyValuePair<ClaimKey, ClaimRecord>[] array = _records.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<ClaimKey, ClaimRecord> keyValuePair = array[i];
				int? terminalStage = keyValuePair.Value.TerminalStage;
				if (terminalStage.HasValue && terminalStage.Value < stageExclusive)
				{
					_records.Remove(keyValuePair.Key);
					num++;
				}
			}
			KeyValuePair<HistoricalClaimKey, HistoricalClaimRecord>[] array2 = _history.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<HistoricalClaimKey, HistoricalClaimRecord> keyValuePair2 = array2[i];
				if (keyValuePair2.Value.Stage < stageExclusive)
				{
					_history.Remove(keyValuePair2.Key);
					num++;
				}
			}
			return num;
		}

		private void SetHistory(SharedPickupKey pickup, StableUserKey stableUser, HistoricalClaimState state, int stage)
		{
			HistoricalClaimKey key = new HistoricalClaimKey(pickup, stableUser);
			if (_history.TryGetValue(key, out HistoricalClaimRecord value))
			{
				if (value.State != state)
				{
					if (value.State == HistoricalClaimState.Collected || value.State == HistoricalClaimState.GrantedDeferred)
					{
						return;
					}
					value.State = state;
				}
				if (stage > value.Stage)
				{
					value.Stage = stage;
				}
			}
			else
			{
				_history.Add(key, new HistoricalClaimRecord(key, state, stage));
			}
		}
	}
	public enum CommandOptionPickupSource
	{
		None,
		NestedPickup,
		DirectCompatibilityFallback
	}
	public readonly struct CommandOptionPickupDecision<T>
	{
		public bool HasValue { get; }

		public T Value { get; }

		public CommandOptionPickupSource Source { get; }

		public bool ExactSource { get; }

		public bool Disagreement { get; }

		public CommandOptionPickupDecision(bool hasValue, T value, CommandOptionPickupSource source, bool exactSource, bool disagreement)
		{
			HasValue = hasValue;
			Value = value;
			Source = source;
			ExactSource = exactSource;
			Disagreement = disagreement;
		}
	}
	public static class CommandOptionSourcePolicy
	{
		public const string AuthoritativeSourceToken = "nested-pickup";

		public const string FallbackSourceToken = "direct-fallback";

		public const string UnresolvedSourceToken = "unresolved";

		public static CommandOptionPickupDecision<T> Resolve<T>(bool nestedAvailable, T nestedValue, bool directAvailable, T directValue)
		{
			if (nestedAvailable)
			{
				bool disagreement = directAvailable && !EqualityComparer<T>.Default.Equals(nestedValue, directValue);
				return new CommandOptionPickupDecision<T>(hasValue: true, nestedValue, CommandOptionPickupSource.NestedPickup, exactSource: true, disagreement);
			}
			if (directAvailable)
			{
				return new CommandOptionPickupDecision<T>(hasValue: true, directValue, CommandOptionPickupSource.DirectCompatibilityFallback, exactSource: false, disagreement: false);
			}
			return new CommandOptionPickupDecision<T>(hasValue: false, default(T), CommandOptionPickupSource.None, exactSource: false, disagreement: false);
		}

		public static string SourceToken(CommandOptionPickupSource source)
		{
			return source switch
			{
				CommandOptionPickupSource.NestedPickup => "nested-pickup", 
				CommandOptionPickupSource.DirectCompatibilityFallback => "direct-fallback", 
				_ => "unresolved", 
			};
		}
	}
	public enum CommandShareabilityState
	{
		Unresolved,
		AllShareable,
		AllUnshareable,
		Mixed
	}
	public readonly struct CommandShareabilityDecision
	{
		public CommandShareabilityState State { get; }

		public bool MarkerEligible => State == CommandShareabilityState.AllShareable;

		public string DiagnosticToken => State switch
		{
			CommandShareabilityState.AllShareable => "all-shareable", 
			CommandShareabilityState.AllUnshareable => "all-unshareable", 
			CommandShareabilityState.Mixed => "mixed", 
			_ => "unresolved", 
		};

		public string FilterReason => State switch
		{
			CommandShareabilityState.AllUnshareable => "upstream-not-shareable", 
			CommandShareabilityState.Mixed => "mixed-shareability", 
			CommandShareabilityState.Unresolved => "shareability-unresolved", 
			_ => string.Empty, 
		};

		public CommandShareabilityDecision(CommandShareabilityState state)
		{
			State = state;
		}
	}
	public static class CommandShareabilityPolicy
	{
		public static CommandShareabilityDecision Evaluate(IReadOnlyList<bool?> optionShareability, IReadOnlyList<bool> excludedOptions)
		{
			if (optionShareability.Count != excludedOptions.Count)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Unresolved);
			}
			List<bool?> list = new List<bool?>(optionShareability.Count);
			bool flag = false;
			for (int i = 0; i < optionShareability.Count; i++)
			{
				if (excludedOptions[i])
				{
					flag = true;
				}
				else
				{
					list.Add(optionShareability[i]);
				}
			}
			if (list.Count == 0 && flag)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.AllUnshareable);
			}
			return Evaluate(list);
		}

		public static CommandShareabilityDecision Evaluate(IEnumerable<bool?>? optionShareability)
		{
			if (optionShareability == null)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Unresolved);
			}
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			foreach (bool? item in optionShareability)
			{
				flag = true;
				if (!item.HasValue)
				{
					return new CommandShareabilityDecision(CommandShareabilityState.Unresolved);
				}
				if (item.Value)
				{
					flag2 = true;
				}
				else
				{
					flag3 = true;
				}
			}
			if (!flag)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Unresolved);
			}
			if (flag2 && flag3)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Mixed);
			}
			if (flag2)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.AllShareable);
			}
			return new CommandShareabilityDecision(CommandShareabilityState.AllUnshareable);
		}
	}
	public enum DiagnosticSeverity
	{
		Error,
		Warning,
		Info,
		Debug
	}
	public static class DiagnosticPolicy
	{
		public static bool Allows(bool enabled, string? level, DiagnosticSeverity severity)
		{
			if (!enabled)
			{
				return false;
			}
			DiagnosticSeverity diagnosticSeverity = ((!string.Equals(level, "Error", StringComparison.OrdinalIgnoreCase)) ? (string.Equals(level, "Warning", StringComparison.OrdinalIgnoreCase) ? DiagnosticSeverity.Warning : (string.Equals(level, "Debug", StringComparison.OrdinalIgnoreCase) ? DiagnosticSeverity.Debug : DiagnosticSeverity.Info)) : DiagnosticSeverity.Error);
			return severity <= diagnosticSeverity;
		}

		public static string ExactRemoteOperation(string? evidence)
		{
			if (string.IsNullOrEmpty(evidence))
			{
				return "not-probed";
			}
			int num = evidence.IndexOf("exactRemoteOperationPreset=", StringComparison.Ordinal);
			if (num < 0)
			{
				return "unavailable-or-not-probed";
			}
			int start = num + "exactRemoteOperationPreset=".Length;
			if (Matches(evidence, start, "true"))
			{
				return "true";
			}
			if (Matches(evidence, start, "false"))
			{
				return "false";
			}
			return "unavailable-fail-closed";
		}

		private static bool Matches(string evidence, int start, string value)
		{
			if (evidence.IndexOf(value, start, StringComparison.Ordinal) != start)
			{
				return false;
			}
			int num = start + value.Length;
			if (num != evidence.Length && evidence[num] != ';')
			{
				return char.IsWhiteSpace(evidence[num]);
			}
			return true;
		}
	}
	public enum NetworkDestroyDisposition
	{
		IgnoreStillAuthoritative,
		HoldForAuthoritativeConfirmation
	}
	public static class DisconnectConfirmationPolicy
	{
		public static bool AllowsImmediateCancelFromNetworkDestroy => false;

		public static bool UsesObjectNamePrefabOrBodyHeuristics => false;

		public static NetworkDestroyDisposition EvaluateNetworkDestroy(bool participantResolved, bool authoritativePresence)
		{
			if (!(participantResolved && authoritativePresence))
			{
				return NetworkDestroyDisposition.HoldForAuthoritativeConfirmation;
			}
			return NetworkDestroyDisposition.IgnoreStillAuthoritative;
		}

		public static bool ShouldConfirmDisconnect(bool participantAbsentFromAuthoritativeControllerList, bool absenceGraceElapsed)
		{
			return participantAbsentFromAuthoritativeControllerList && absenceGraceElapsed;
		}
	}
	public enum DlcPickupKind
	{
		Other,
		Hallowed,
		Hex,
		Page
	}
	public readonly struct DlcSharingSettings
	{
		public bool Hallowed { get; }

		public bool Hex { get; }

		public bool Pages { get; }

		public DlcSharingSettings(bool hallowed, bool hex, bool pages)
		{
			Hallowed = hallowed;
			Hex = hex;
			Pages = pages;
		}

		public bool Allows(DlcPickupKind kind)
		{
			return kind switch
			{
				DlcPickupKind.Page => Pages, 
				DlcPickupKind.Hex => Hex, 
				DlcPickupKind.Hallowed => Hallowed, 
				_ => false, 
			};
		}
	}
	public static class DlcPickupSharingPolicy
	{
		public static bool CanShare(DlcPickupKind kind, DlcSharingSettings settings, bool hidden, bool consumed, bool worldUnique, bool objectiveRelated, bool progressionExcluded, bool activePageSpell)
		{
			if (settings.Allows(kind) && !hidden && !consumed && !worldUnique && !objectiveRelated && !progressionExcluded)
			{
				return kind != DlcPickupKind.Page || activePageSpell;
			}
			return false;
		}
	}
	public sealed class SharedInteractionContext<T> where T : class
	{
		private sealed class Frame : IDisposable
		{
			private readonly SharedInteractionContext<T> _owner;

			private bool _disposed;

			public T? Key { get; }

			public bool AlreadyOwned { get; }

			public Frame(SharedInteractionContext<T> owner, T? key, bool alreadyOwned)
			{
				_owner = owner;
				Key = key;
				AlreadyOwned = alreadyOwned;
			}

			public void Dispose()
			{
				if (!_disposed)
				{
					if (_owner._frames.Count == 0 || _owner._frames.Peek() != this)
					{
						throw new InvalidOperationException("Shared pickup scope disposal order mismatch.");
					}
					_owner._frames.Pop();
					_disposed = true;
				}
			}
		}

		private readonly Stack<Frame> _frames = new Stack<Frame>();

		public IDisposable Enter(T? key, bool alreadyOwned)
		{
			Frame frame = new Frame(this, key, alreadyOwned);
			_frames.Push(frame);
			return frame;
		}

		public bool IsOwned(T key)
		{
			if (_frames.Count > 0 && _frames.Peek().AlreadyOwned)
			{
				return _frames.Peek().Key == key;
			}
			return false;
		}
	}
	public sealed class SharedOptionPolicy<T> where T : class
	{
		private readonly HashSet<T> _allowed = new HashSet<T>();

		public IEnumerable<T> Allowed => _allowed;

		public void Clear()
		{
			_allowed.Clear();
		}

		public bool Contains(T option)
		{
			return _allowed.Contains(option);
		}

		public void Observe(T option, bool alreadyShared, bool currentlyShareable)
		{
			if (currentlyShareable)
			{
				_allowed.Add(option);
			}
			else if (!alreadyShared)
			{
				_allowed.Remove(option);
			}
		}
	}
	public enum GenerationProbeState
	{
		NeverResolved,
		Resolved,
		Frozen
	}
	public enum UnsupportedProbeDisposition
	{
		NoOwnershipEstablished,
		FreezePreserveExistingState
	}
	public sealed class GenerationProbeGate
	{
		private ParticipantKey? _provenParticipant;

		public GenerationProbeState State { get; private set; }

		public bool HasProvenParticipant => _provenParticipant.HasValue;

		public ParticipantKey ProvenParticipant => _provenParticipant ?? throw new InvalidOperationException("No proven participant exists for this generation.");

		public bool CanCreateClaims => State == GenerationProbeState.Resolved;

		public bool CanUseHistoricalBarrier => HasProvenParticipant;

		public bool CanGrantDeferred(ParticipantState exactState)
		{
			if (State == GenerationProbeState.Resolved)
			{
				return exactState == ParticipantState.Alive;
			}
			return false;
		}

		public bool TryResolve(ParticipantKey participant)
		{
			if (_provenParticipant.HasValue && !_provenParticipant.Value.Equals(participant))
			{
				return false;
			}
			_provenParticipant = participant;
			State = GenerationProbeState.Resolved;
			return true;
		}

		public UnsupportedProbeDisposition ObserveUnsupported()
		{
			if (!_provenParticipant.HasValue)
			{
				State = GenerationProbeState.NeverResolved;
				return UnsupportedProbeDisposition.NoOwnershipEstablished;
			}
			State = GenerationProbeState.Frozen;
			return UnsupportedProbeDisposition.FreezePreserveExistingState;
		}
	}
	public enum ImmediateGiveDecision
	{
		AllowUpstream,
		SuppressHistoricalBarrier,
		SuppressFullyDeadDeferred,
		SuppressExistingDeferredEntitlement
	}
	public static class ImmediateGivePolicy
	{
		public static ImmediateGiveDecision Decide(bool stableIdentityResolved, ParticipantState? participantState, bool deadPlayerDeferredItemsEnabled, bool historicalBarrierForCurrentPickup, bool deferredEntitlementReadyForCurrentPickup = false)
		{
			if (!stableIdentityResolved)
			{
				return ImmediateGiveDecision.AllowUpstream;
			}
			if (historicalBarrierForCurrentPickup)
			{
				return ImmediateGiveDecision.SuppressHistoricalBarrier;
			}
			if (deferredEntitlementReadyForCurrentPickup)
			{
				if (participantState.HasValue && participantState.Value == ParticipantState.FullyDead && deadPlayerDeferredItemsEnabled)
				{
					return ImmediateGiveDecision.SuppressFullyDeadDeferred;
				}
				return ImmediateGiveDecision.SuppressExistingDeferredEntitlement;
			}
			return ImmediateGiveDecision.AllowUpstream;
		}

		public static bool ShouldSuppress(bool stableIdentityResolved, ParticipantState? participantState, bool deadPlayerDeferredItemsEnabled, bool historicalBarrierForCurrentPickup, bool deferredEntitlementReadyForCurrentPickup = false)
		{
			return Decide(stableIdentityResolved, participantState, deadPlayerDeferredItemsEnabled, historicalBarrierForCurrentPickup, deferredEntitlementReadyForCurrentPickup) != ImmediateGiveDecision.AllowUpstream;
		}
	}
	public static class ItemShareActiveGatePolicy
	{
		public static bool ShouldCorrectIsDown(bool upstreamOriginalIsDown, bool authoritativeControllerPresent, bool exactGenerationProven, ParticipantState participantState)
		{
			if (upstreamOriginalIsDown && authoritativeControllerPresent && exactGenerationProven)
			{
				return participantState == ParticipantState.SupportDrone;
			}
			return false;
		}

		public static bool CorrectIsDown(bool upstreamOriginalIsDown, bool authoritativeControllerPresent, bool exactGenerationProven, ParticipantState participantState)
		{
			if (!ShouldCorrectIsDown(upstreamOriginalIsDown, authoritativeControllerPresent, exactGenerationProven, participantState))
			{
				return upstreamOriginalIsDown;
			}
			return false;
		}

		public static bool CountsAsOutstandingCollector(bool authoritativeControllerPresent, ParticipantState participantState)
		{
			if (authoritativeControllerPresent)
			{
				if (participantState != ParticipantState.Alive)
				{
					return participantState == ParticipantState.SupportDrone;
				}
				return true;
			}
			return false;
		}

		public static bool IsDeadAutoShareTarget(bool upstreamOriginalIsDown, bool authoritativeControllerPresent, bool exactGenerationProven, ParticipantState participantState)
		{
			return CorrectIsDown(upstreamOriginalIsDown, authoritativeControllerPresent, exactGenerationProven, participantState);
		}
	}
	public readonly struct LocalCommandPresentationDecision
	{
		public bool AllLocalStateResolved { get; }

		public bool AnyLocalPending { get; }

		public bool SuppressWorldPresentation { get; }

		public LocalCommandPresentationDecision(bool allLocalStateResolved, bool anyLocalPending, bool suppressWorldPresentation)
		{
			AllLocalStateResolved = allLocalStateResolved;
			AnyLocalPending = anyLocalPending;
			SuppressWorldPresentation = suppressWorldPresentation;
		}
	}
	public static class LocalCommandPresentationPolicy
	{
		public static LocalCommandPresentationDecision Evaluate(IReadOnlyList<bool?> localPickedStates)
		{
			if (localPickedStates == null)
			{
				throw new ArgumentNullException("localPickedStates");
			}
			if (localPickedStates.Count == 0)
			{
				return new LocalCommandPresentationDecision(allLocalStateResolved: false, anyLocalPending: false, suppressWorldPresentation: false);
			}
			bool flag = true;
			bool flag2 = false;
			for (int i = 0; i < localPickedStates.Count; i++)
			{
				bool? flag3 = localPickedStates[i];
				if (!flag3.HasValue)
				{
					flag = false;
				}
				else if (!flag3.Value)
				{
					flag2 = true;
				}
			}
			bool suppressWorldPresentation = flag && !flag2;
			return new LocalCommandPresentationDecision(flag, flag2, suppressWorldPresentation);
		}
	}
	public static class LocalParticipantPresentationPolicy
	{
		public static ParticipantState Classify(bool masterAvailable, bool exactRemoteOperationSignal, bool bodyPresent)
		{
			if (!masterAvailable)
			{
				return ParticipantState.Disconnected;
			}
			if (exactRemoteOperationSignal)
			{
				return ParticipantState.SupportDrone;
			}
			if (bodyPresent)
			{
				return ParticipantState.Alive;
			}
			return ParticipantState.FullyDead;
		}
	}
	public static class LocalPickupSuppressionPolicy
	{
		public static bool AllowsAuthoritativePickupDestroy => false;

		public static bool AllowsSharedRootDisable => false;

		public static bool AllowsSharedColliderDisable => false;

		public static bool ShouldSuppressProcessVisual(bool featureEnabled, bool upstreamHideCollectedEnabled, int localParticipantCount, int collectedLocalParticipantCount)
		{
			if (featureEnabled && upstreamHideCollectedEnabled && localParticipantCount > 0)
			{
				return collectedLocalParticipantCount == localParticipantCount;
			}
			return false;
		}

		public static bool ShouldSuppressInteractor(bool featureEnabled, bool upstreamHideCollectedEnabled, bool shareablePickup, bool interactorIsLocal, bool interactorHasCollected)
		{
			return featureEnabled && upstreamHideCollectedEnabled && shareablePickup && interactorIsLocal && interactorHasCollected;
		}
	}
	public readonly struct MarkerExpansionCandidate
	{
		public long ClusterKey { get; }

		public int MemberCount { get; }

		public float DistanceMeters { get; }

		public float ReticleDistancePixels1080 { get; }

		public MarkerExpansionCandidate(long clusterKey, int memberCount, float distanceMeters, float reticleDistancePixels1080)
		{
			ClusterKey = clusterKey;
			MemberCount = Math.Max(0, memberCount);
			DistanceMeters = distanceMeters;
			ReticleDistancePixels1080 = reticleDistancePixels1080;
		}
	}
	public sealed class MarkerAdaptiveLodTracker
	{
		public const int DenseClusterMinimumMembers = 3;

		public const float FocusEnterPixels1080 = 72f;

		public const float FocusExitPixels1080 = 110f;

		public const float NearEnterMeters = 18f;

		public const float NearExitMeters = 22f;

		public const float UniqueNearestMarginMeters = 1f;

		public const double FocusAcquireDwellSeconds = 0.12;

		public const double NearAcquireDwellSeconds = 0.25;

		public const double ReleaseDwellSeconds = 0.2;

		private long? _expandedKey;

		private long? _pendingKey;

		private double _pendingSince;

		private bool _pendingRelease;

		public long? ExpandedKey => _expandedKey;

		public long? Update(IReadOnlyList<MarkerExpansionCandidate> candidates, double nowSeconds)
		{
			if (candidates == null)
			{
				throw new ArgumentNullException("candidates");
			}
			if (double.IsNaN(nowSeconds) || double.IsInfinity(nowSeconds))
			{
				nowSeconds = 0.0;
			}
			if (_expandedKey.HasValue && IsCurrentStillQualified(candidates, _expandedKey.Value))
			{
				long? num = FindFocused(candidates, useExitForCurrent: true);
				if (!num.HasValue || num.Value == _expandedKey.Value)
				{
					ResetPending();
					return _expandedKey;
				}
			}
			long? num2 = FindFocused(candidates, useExitForCurrent: false);
			if (num2.HasValue)
			{
				return AdvanceToward(num2.Value, nowSeconds, 0.12);
			}
			long? num3 = FindUniqueNearest(candidates);
			if (num3.HasValue)
			{
				return AdvanceToward(num3.Value, nowSeconds, 0.25);
			}
			if (!_expandedKey.HasValue)
			{
				ResetPending();
				return null;
			}
			if (!_pendingRelease)
			{
				_pendingRelease = true;
				_pendingKey = null;
				_pendingSince = nowSeconds;
				return _expandedKey;
			}
			if (nowSeconds - _pendingSince < 0.2)
			{
				return _expandedKey;
			}
			_expandedKey = null;
			ResetPending();
			return null;
		}

		public void Clear()
		{
			_expandedKey = null;
			ResetPending();
		}

		private long? AdvanceToward(long desiredKey, double nowSeconds, double dwellSeconds)
		{
			_pendingRelease = false;
			if (_expandedKey.HasValue && _expandedKey.Value == desiredKey)
			{
				ResetPending();
				return _expandedKey;
			}
			if (!_pendingKey.HasValue || _pendingKey.Value != desiredKey)
			{
				_pendingKey = desiredKey;
				_pendingSince = nowSeconds;
				return _expandedKey;
			}
			if (nowSeconds - _pendingSince < dwellSeconds)
			{
				return _expandedKey;
			}
			_expandedKey = desiredKey;
			ResetPending();
			return _expandedKey;
		}

		private bool IsCurrentStillQualified(IReadOnlyList<MarkerExpansionCandidate> candidates, long key)
		{
			for (int i = 0; i < candidates.Count; i++)
			{
				MarkerExpansionCandidate markerExpansionCandidate = candidates[i];
				if (markerExpansionCandidate.ClusterKey == key && markerExpansionCandidate.MemberCount >= 3)
				{
					if (!(markerExpansionCandidate.ReticleDistancePixels1080 <= 110f))
					{
						return markerExpansionCandidate.DistanceMeters <= 22f;
					}
					return true;
				}
			}
			return false;
		}

		private long? FindFocused(IReadOnlyList<MarkerExpansionCandidate> candidates, bool useExitForCurrent)
		{
			float num = (useExitForCurrent ? 110f : 72f);
			bool flag = false;
			MarkerExpansionCandidate markerExpansionCandidate = default(MarkerExpansionCandidate);
			for (int i = 0; i < candidates.Count; i++)
			{
				MarkerExpansionCandidate markerExpansionCandidate2 = candidates[i];
				if (markerExpansionCandidate2.MemberCount >= 3 && IsFiniteNonNegative(markerExpansionCandidate2.ReticleDistancePixels1080) && !(markerExpansionCandidate2.ReticleDistancePixels1080 > num) && (!flag || markerExpansionCandidate2.ReticleDistancePixels1080 < markerExpansionCandidate.ReticleDistancePixels1080 || (Math.Abs(markerExpansionCandidate2.ReticleDistancePixels1080 - markerExpansionCandidate.ReticleDistancePixels1080) <= 0.001f && (markerExpansionCandidate2.DistanceMeters < markerExpansionCandidate.DistanceMeters || (Math.Abs(markerExpansionCandidate2.DistanceMeters - markerExpansionCandidate.DistanceMeters) <= 0.001f && markerExpansionCandidate2.ClusterKey < markerExpansionCandidate.ClusterKey)))))
				{
					flag = true;
					markerExpansionCandidate = markerExpansionCandidate2;
				}
			}
			if (!flag)
			{
				return null;
			}
			return markerExpansionCandidate.ClusterKey;
		}

		private static long? FindUniqueNearest(IReadOnlyList<MarkerExpansionCandidate> candidates)
		{
			bool flag = false;
			MarkerExpansionCandidate markerExpansionCandidate = default(MarkerExpansionCandidate);
			float num = float.PositiveInfinity;
			for (int i = 0; i < candidates.Count; i++)
			{
				MarkerExpansionCandidate markerExpansionCandidate2 = candidates[i];
				if (markerExpansionCandidate2.MemberCount < 3 || !IsFiniteNonNegative(markerExpansionCandidate2.DistanceMeters) || markerExpansionCandidate2.DistanceMeters > 18f)
				{
					continue;
				}
				if (!flag || markerExpansionCandidate2.DistanceMeters < markerExpansionCandidate.DistanceMeters || (Math.Abs(markerExpansionCandidate2.DistanceMeters - markerExpansionCandidate.DistanceMeters) <= 0.001f && markerExpansionCandidate2.ClusterKey < markerExpansionCandidate.ClusterKey))
				{
					if (flag)
					{
						num = markerExpansionCandidate.DistanceMeters;
					}
					markerExpansionCandidate = markerExpansionCandidate2;
					flag = true;
				}
				else if (markerExpansionCandidate2.DistanceMeters < num)
				{
					num = markerExpansionCandidate2.DistanceMeters;
				}
			}
			if (!flag)
			{
				return null;
			}
			if (!float.IsPositiveInfinity(num) && num - markerExpansionCandidate.DistanceMeters < 1f)
			{
				return null;
			}
			return markerExpansionCandidate.ClusterKey;
		}

		private void ResetPending()
		{
			_pendingKey = null;
			_pendingRelease = false;
			_pendingSince = 0.0;
		}

		private static bool IsFiniteNonNegative(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return value >= 0f;
			}
			return false;
		}
	}
	public enum MarkerCategorySortOrder
	{
		HighToLow,
		LowToHigh
	}
	public readonly struct MarkerCompactLayoutSlot
	{
		public int Row { get; }

		public int Column { get; }

		public int RowSize { get; }

		public float XUnits { get; }

		public float YUnits { get; }

		public MarkerCompactLayoutSlot(int row, int column, int rowSize, float xUnits, float yUnits)
		{
			Row = row;
			Column = column;
			RowSize = rowSize;
			XUnits = xUnits;
			YUnits = yUnits;
		}
	}
	public readonly struct MarkerCompactCellGeometry
	{
		public float BadgeSize { get; }

		public float CountWidth { get; }

		public float CountGap { get; }

		public float CellWidth { get; }

		public float HorizontalStride { get; }

		public float VerticalStride { get; }

		public MarkerCompactCellGeometry(float badgeSize, float countWidth, float countGap, float cellWidth, float horizontalStride, float verticalStride)
		{
			BadgeSize = badgeSize;
			CountWidth = countWidth;
			CountGap = countGap;
			CellWidth = cellWidth;
			HorizontalStride = horizontalStride;
			VerticalStride = verticalStride;
		}
	}
	public static class MarkerCategorySummaryPolicy
	{
		public const MarkerCategorySortOrder DefaultSortOrder = MarkerCategorySortOrder.HighToLow;

		public const float PyramidMaxVerticalOffsetUnits = 0.6f;

		public const float PyramidMinimumHorizontalSpacingFactor = 0.62f;

		public const int MaxCategories = 14;

		public static int DisplayPriority(MarkerSemanticCategory category)
		{
			return category switch
			{
				MarkerSemanticCategory.Tier3 => 110, 
				MarkerSemanticCategory.Boss => 100, 
				MarkerSemanticCategory.Lunar => 90, 
				MarkerSemanticCategory.Void => 80, 
				MarkerSemanticCategory.Tier2 => 70, 
				MarkerSemanticCategory.Equipment => 60, 
				MarkerSemanticCategory.LunarEquipment => 50, 
				MarkerSemanticCategory.Tier1 => 40, 
				MarkerSemanticCategory.CommandState => 30, 
				MarkerSemanticCategory.Other => 20, 
				MarkerSemanticCategory.Hallowed => 115, 
				MarkerSemanticCategory.Hex => 35, 
				MarkerSemanticCategory.Page => 85, 
				_ => 10, 
			};
		}

		public static MarkerCompactCategoryBadge[] BuildCategoryEntries(IReadOnlyList<MarkerCategoryCount> composition, MarkerCategorySortOrder sortOrder)
		{
			if (composition == null)
			{
				throw new ArgumentNullException("composition");
			}
			int num = 0;
			for (int i = 0; i < composition.Count; i++)
			{
				if (num >= 14)
				{
					break;
				}
				if (composition[i].Count > 0)
				{
					num++;
				}
			}
			MarkerCompactCategoryBadge[] array = new MarkerCompactCategoryBadge[num];
			int num2 = 0;
			for (int j = 0; j < composition.Count; j++)
			{
				if (num2 >= array.Length)
				{
					break;
				}
				MarkerCategoryCount markerCategoryCount = composition[j];
				if (markerCategoryCount.Count > 0)
				{
					array[num2++] = new MarkerCompactCategoryBadge(markerCategoryCount.Category, markerCategoryCount.Count, DisplayPriority(markerCategoryCount.Category));
				}
			}
			for (int k = 1; k < array.Length; k++)
			{
				MarkerCompactCategoryBadge markerCompactCategoryBadge = array[k];
				int num3 = k - 1;
				while (num3 >= 0 && Compare(markerCompactCategoryBadge, array[num3], sortOrder) < 0)
				{
					array[num3 + 1] = array[num3];
					num3--;
				}
				array[num3 + 1] = markerCompactCategoryBadge;
			}
			return array;
		}

		public static float PyramidVerticalOffsetUnits(MarkerSemanticCategory category)
		{
			float num = ((float)DisplayPriority(category) - 10f) / 100f;
			if (num < 0f)
			{
				num = 0f;
			}
			if (num > 1f)
			{
				num = 1f;
			}
			return num * 0.6f;
		}

		public static float PyramidHorizontalSpacingFactor(int categoryCount)
		{
			if (categoryCount <= 3)
			{
				return 1f;
			}
			float num = 1f - (float)(categoryCount - 3) * 0.055f;
			if (!(num < 0.62f))
			{
				return num;
			}
			return 0.62f;
		}

		public static float BuildCategoryGlyphSize(float screenWidth, float screenHeight, float markerScale, float indicatorSize, float fontSize)
		{
			float num = (IsFinitePositive(screenWidth) ? screenWidth : 1920f);
			float num2 = (IsFinitePositive(screenHeight) ? screenHeight : 1080f);
			float num3 = (IsFinitePositive(markerScale) ? markerScale : 1f);
			if (num3 < 0.75f)
			{
				num3 = 0.75f;
			}
			if (num3 > 1.25f)
			{
				num3 = 1.25f;
			}
			float num4 = Math.Min(num / 1920f, num2 / 1080f);
			if (!IsFinitePositive(num4))
			{
				num4 = 1f;
			}
			float num5 = num4 * num3;
			float num6 = (IsFinitePositive(indicatorSize) ? indicatorSize : (24f * num5));
			float num7 = (IsFinitePositive(fontSize) ? fontSize : (20f * num5));
			return Math.Max(12f * num5, Math.Min(num6 * 0.58f, num7 * 0.78f));
		}

		public static float BuildCompactLifetimeGroupGap(float screenWidth, float screenHeight, float markerScale, float indicatorSize, float fontSize)
		{
			float num = (IsFinitePositive(screenWidth) ? screenWidth : 1920f);
			float num2 = (IsFinitePositive(screenHeight) ? screenHeight : 1080f);
			float num3 = (IsFinitePositive(markerScale) ? markerScale : 1f);
			if (num3 < 0.75f)
			{
				num3 = 0.75f;
			}
			if (num3 > 1.25f)
			{
				num3 = 1.25f;
			}
			float num4 = Math.Min(num / 1920f, num2 / 1080f);
			if (!IsFinitePositive(num4))
			{
				num4 = 1f;
			}
			float num5 = num4 * num3;
			float indicatorSize2 = (IsFinitePositive(indicatorSize) ? indicatorSize : (24f * num5));
			float fontSize2 = (IsFinitePositive(fontSize) ? fontSize : (20f * num5));
			float num6 = BuildCategoryGlyphSize(num, num2, num3, indicatorSize2, fontSize2);
			return Math.Max(4f * num5, num6 * 0.18f);
		}

		public static float BuildCompactCategoryCenterHorizontalStride(float screenWidth, float screenHeight, float markerScale, float indicatorSize, float fontSize, int categoryCount)
		{
			float num = (IsFinitePositive(screenWidth) ? screenWidth : 1920f);
			float num2 = (IsFinitePositive(screenHeight) ? screenHeight : 1080f);
			float num3 = (IsFinitePositive(markerScale) ? markerScale : 1f);
			if (num3 < 0.75f)
			{
				num3 = 0.75f;
			}
			if (num3 > 1.25f)
			{
				num3 = 1.25f;
			}
			float num4 = Math.Min(num / 1920f, num2 / 1080f);
			if (!IsFinitePositive(num4))
			{
				num4 = 1f;
			}
			float num5 = num4 * num3;
			float indicatorSize2 = (IsFinitePositive(indicatorSize) ? indicatorSize : (24f * num5));
			float fontSize2 = (IsFinitePositive(fontSize) ? fontSize : (20f * num5));
			MarkerCompactCellGeometry markerCompactCellGeometry = BuildCompactCellGeometry(num, num2, num3, indicatorSize2, fontSize2, showCount: false);
			float num6 = BuildCompactLifetimeGroupGap(num, num2, num3, indicatorSize2, fontSize2);
			float num7 = Math.Max(4f * num5, markerCompactCellGeometry.BadgeSize * 0.18f);
			float num8 = markerCompactCellGeometry.HorizontalStride * PyramidHorizontalSpacingFactor(categoryCount);
			MarkerCompactLayoutSlot[] array = BuildCompactLayout(categoryCount);
			bool flag = false;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i].RowSize >= 3)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return num8;
			}
			float val = markerCompactCellGeometry.BadgeSize * 1.5f + num6 * 0.5f + num7;
			return Math.Max(num8, val);
		}

		public static float BuildCompactCategoryCenterVerticalStride(float screenWidth, float screenHeight, float markerScale, float indicatorSize, float fontSize)
		{
			return BuildCompactCellGeometry(screenWidth, screenHeight, markerScale, indicatorSize, fontSize, showCount: false).VerticalStride;
		}

		public static float BuildDetailedCategoryDistanceGap(float screenWidth, float screenHeight, float markerScale, float indicatorSize, float fontSize)
		{
			float num = (IsFinitePositive(screenWidth) ? screenWidth : 1920f);
			float num2 = (IsFinitePositive(screenHeight) ? screenHeight : 1080f);
			float num3 = (IsFinitePositive(markerScale) ? markerScale : 1f);
			if (num3 < 0.75f)
			{
				num3 = 0.75f;
			}
			if (num3 > 1.25f)
			{
				num3 = 1.25f;
			}
			float num4 = Math.Min(num / 1920f, num2 / 1080f);
			if (!IsFinitePositive(num4))
			{
				num4 = 1f;
			}
			float num5 = num4 * num3;
			float indicatorSize2 = (IsFinitePositive(indicatorSize) ? indicatorSize : (24f * num5));
			float num6 = (IsFinitePositive(fontSize) ? fontSize : (20f * num5));
			float num7 = BuildCategoryGlyphSize(num, num2, num3, indicatorSize2, num6);
			float num8 = num6 * 1.18f;
			float num9 = Math.Max(num8, num7 + 2f * num5);
			return Math.Max(0f, num9 - (num7 + num8) * 0.5f);
		}

		public static float BuildCompactLifetimeGroupOffsetX(MarkerCompactLayoutSlot categorySlot, int groupOrdinal, int groupCount, float glyphSize, float lifetimeGroupGap)
		{
			int num = Math.Max(1, groupCount);
			int num2 = Math.Max(0, Math.Min(num - 1, groupOrdinal));
			if (num == 1)
			{
				return 0f;
			}
			float num3 = (IsFinitePositive(glyphSize) ? glyphSize : 1f);
			float num4 = ((!float.IsNaN(lifetimeGroupGap) && !float.IsInfinity(lifetimeGroupGap) && lifetimeGroupGap > 0f) ? lifetimeGroupGap : 0f);
			float num5 = num3 + num4;
			float num6 = (float)(Math.Max(1, categorySlot.RowSize) - 1) * 0.5f;
			if (categorySlot.RowSize > 1 && (float)categorySlot.Column < num6)
			{
				return (float)(-num2) * num5;
			}
			if (categorySlot.RowSize > 1 && (float)categorySlot.Column > num6)
			{
				return (float)num2 * num5;
			}
			return ((float)num2 - (float)(num - 1) * 0.5f) * num5;
		}

		public static MarkerCompactCellGeometry BuildCompactCellGeometry(float screenWidth, float screenHeight, float markerScale, float indicatorSize, float fontSize, bool showCount)
		{
			float num = (IsFinitePositive(screenWidth) ? screenWidth : 1920f);
			float num2 = (IsFinitePositive(screenHeight) ? screenHeight : 1080f);
			float num3 = (IsFinitePositive(markerScale) ? markerScale : 1f);
			if (num3 < 0.75f)
			{
				num3 = 0.75f;
			}
			if (num3 > 1.25f)
			{
				num3 = 1.25f;
			}
			float num4 = Math.Min(num / 1920f, num2 / 1080f);
			if (!IsFinitePositive(num4))
			{
				num4 = 1f;
			}
			float num5 = num4 * num3;
			float indicatorSize2 = (IsFinitePositive(indicatorSize) ? indicatorSize : (24f * num5));
			float num6 = (IsFinitePositive(fontSize) ? fontSize : (20f * num5));
			float num7 = BuildCategoryGlyphSize(num, num2, num3, indicatorSize2, num6);
			float num8 = (showCount ? Math.Max(24f * num5, num6 * 2.2f) : 0f);
			float num9 = (showCount ? Math.Max(5f * num5, num6 * 0.18f) : 0f);
			float num10 = num7 + num9 + num8;
			float num11 = Math.Max(10f * num5, num7 * 0.28f);
			float horizontalStride = num10 + num11;
			float verticalStride = Math.Max(num7 + 10f * num5, num6 * 1.45f);
			return new MarkerCompactCellGeometry(num7, num8, num9, num10, horizontalStride, verticalStride);
		}

		private static bool IsFinitePositive(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return value > 0f;
			}
			return false;
		}

		public static MarkerCompactLayoutSlot[] BuildCompactLayout(int categoryCount)
		{
			int num = Math.Max(0, Math.Min(14, categoryCount));
			if (num == 0)
			{
				return Array.Empty<MarkerCompactLayoutSlot>();
			}
			int[] array = CompactRowPattern(num);
			MarkerCompactLayoutSlot[] array2 = new MarkerCompactLayoutSlot[num];
			int num2 = 0;
			int num3 = array.Length;
			for (int i = 0; i < array.Length; i++)
			{
				int num4 = array[i];
				float yUnits = (float)(num3 - 1) * 0.5f - (float)i;
				for (int j = 0; j < num4; j++)
				{
					if (num2 >= num)
					{
						break;
					}
					float xUnits = (float)j - (float)(num4 - 1) * 0.5f;
					array2[num2++] = new MarkerCompactLayoutSlot(i, j, num4, xUnits, yUnits);
				}
			}
			return array2;
		}

		private static int[] CompactRowPattern(int count)
		{
			return count switch
			{
				1 => new int[1] { 1 }, 
				2 => new int[2] { 1, 1 }, 
				3 => new int[2] { 1, 2 }, 
				4 => new int[3] { 1, 2, 1 }, 
				5 => new int[3] { 1, 3, 1 }, 
				6 => new int[4] { 1, 2, 2, 1 }, 
				7 => new int[4] { 1, 2, 3, 1 }, 
				8 => new int[5] { 1, 2, 2, 2, 1 }, 
				9 => new int[5] { 1, 2, 3, 2, 1 }, 
				10 => new int[5] { 1, 2, 3, 3, 1 }, 
				12 => new int[6] { 1, 2, 3, 3, 2, 1 }, 
				13 => new int[6] { 1, 2, 3, 3, 3, 1 }, 
				14 => new int[6] { 1, 3, 3, 3, 3, 1 }, 
				_ => new int[5] { 1, 3, 3, 3, 1 }, 
			};
		}

		private static int Compare(MarkerCompactCategoryBadge left, MarkerCompactCategoryBadge right, MarkerCategorySortOrder sortOrder)
		{
			int num = right.DisplayPriority.CompareTo(left.DisplayPriority);
			if (sortOrder == MarkerCategorySortOrder.LowToHigh)
			{
				num = -num;
			}
			if (num != 0)
			{
				return num;
			}
			int num2 = MarkerSemanticCategoryPolicy.StableOrder(left.Category).CompareTo(MarkerSemanticCategoryPolicy.StableOrder(right.Category));
			if (sortOrder != MarkerCategorySortOrder.LowToHigh)
			{
				return num2;
			}
			return -num2;
		}
	}
	public enum MarkerClassKind
	{
		Unknown,
		Tier1,
		Tier2,
		Tier3,
		Boss,
		Lunar,
		Void,
		Equipment,
		LunarEquipment,
		Other,
		Hallowed,
		Hex,
		Page
	}
	public readonly struct CommandClassPresentation
	{
		public MarkerClassKind Kind { get; }

		public string Label { get; }

		public bool ExactClass { get; }

		public CommandClassPresentation(MarkerClassKind kind, string label, bool exactClass)
		{
			Kind = kind;
			Label = (string.IsNullOrWhiteSpace(label) ? "Item choice" : label);
			ExactClass = exactClass;
		}
	}
	public static class MarkerClassPolicy
	{
		public static bool UsesCatalogPickupBaseColor => true;

		public static bool UsesArtifactCommandName => false;

		public static string CommandChoiceSource => "PickupPickerController.options/PickupIndex";

		public static string AuthoritativeCommandChoiceSource => "PickupPickerController.options/option.pickup.pickupIndex";

		public static MarkerClassKind Classify(string? itemTierName, bool isEquipment, bool isLunarEquipment)
		{
			if (isEquipment)
			{
				if (!isLunarEquipment)
				{
					return MarkerClassKind.Equipment;
				}
				return MarkerClassKind.LunarEquipment;
			}
			string text = itemTierName ?? string.Empty;
			if (string.Equals(text, "Tier1", StringComparison.Ordinal))
			{
				return MarkerClassKind.Tier1;
			}
			if (string.Equals(text, "Tier2", StringComparison.Ordinal))
			{
				return MarkerClassKind.Tier2;
			}
			if (string.Equals(text, "Tier3", StringComparison.Ordinal))
			{
				return MarkerClassKind.Tier3;
			}
			if (string.Equals(text, "Boss", StringComparison.Ordinal))
			{
				return MarkerClassKind.Boss;
			}
			if (string.Equals(text, "Lunar", StringComparison.Ordinal))
			{
				return MarkerClassKind.Lunar;
			}
			if (string.Equals(text, "Cursed", StringComparison.Ordinal))
			{
				return MarkerClassKind.Hallowed;
			}
			if (string.Equals(text, "Hex", StringComparison.Ordinal))
			{
				return MarkerClassKind.Hex;
			}
			if (string.Equals(text, "Page", StringComparison.Ordinal))
			{
				return MarkerClassKind.Page;
			}
			if (text.StartsWith("Void", StringComparison.Ordinal))
			{
				return MarkerClassKind.Void;
			}
			if (string.IsNullOrWhiteSpace(text) || string.Equals(text, "NoTier", StringComparison.Ordinal))
			{
				return MarkerClassKind.Unknown;
			}
			return MarkerClassKind.Other;
		}

		public static string DiagnosticClassName(MarkerClassKind kind)
		{
			return kind switch
			{
				MarkerClassKind.Tier1 => "WHITE", 
				MarkerClassKind.Tier2 => "GREEN", 
				MarkerClassKind.Tier3 => "RED", 
				MarkerClassKind.Boss => "YELLOW", 
				MarkerClassKind.Lunar => "LUNAR_BLUE", 
				MarkerClassKind.Void => "VOID_PURPLE", 
				MarkerClassKind.Equipment => "EQUIPMENT", 
				MarkerClassKind.LunarEquipment => "LUNAR_EQUIPMENT", 
				MarkerClassKind.Other => "OTHER", 
				MarkerClassKind.Hallowed => "HALLOWED", 
				MarkerClassKind.Hex => "HEX", 
				MarkerClassKind.Page => "PAGE", 
				_ => "UNKNOWN", 
			};
		}

		public static string LocalizedClassLabel(MarkerClassKind kind, bool russian)
		{
			if (russian)
			{
				return kind switch
				{
					MarkerClassKind.Tier1 => "Белый", 
					MarkerClassKind.Tier2 => "Зелёный", 
					MarkerClassKind.Tier3 => "Красный", 
					MarkerClassKind.Boss => "Жёлтый", 
					MarkerClassKind.Lunar => "Синий", 
					MarkerClassKind.Void => "Фиолетовый", 
					MarkerClassKind.Equipment => "Снаряжение", 
					MarkerClassKind.LunarEquipment => "Лунное снаряжение", 
					_ => "Выбор предмета", 
				};
			}
			return kind switch
			{
				MarkerClassKind.Tier1 => "White", 
				MarkerClassKind.Tier2 => "Green", 
				MarkerClassKind.Tier3 => "Red", 
				MarkerClassKind.Boss => "Yellow", 
				MarkerClassKind.Lunar => "Blue", 
				MarkerClassKind.Void => "Purple", 
				MarkerClassKind.Equipment => "Equipment", 
				MarkerClassKind.LunarEquipment => "Lunar equipment", 
				_ => "Item choice", 
			};
		}

		public static CommandClassPresentation ResolveCommandClass(IEnumerable<MarkerClassKind>? choiceClasses, bool russian)
		{
			if (choiceClasses == null)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedClassLabel(MarkerClassKind.Unknown, russian), exactClass: false);
			}
			MarkerClassKind[] array = choiceClasses.ToArray();
			if (array.Length == 0 || array.Any((MarkerClassKind x) => x == MarkerClassKind.Unknown))
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedClassLabel(MarkerClassKind.Unknown, russian), exactClass: false);
			}
			MarkerClassKind[] array2 = array.Distinct().ToArray();
			if (array2.Length != 1)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedClassLabel(MarkerClassKind.Unknown, russian), exactClass: false);
			}
			MarkerClassKind markerClassKind = array2[0];
			if (markerClassKind == MarkerClassKind.Other)
			{
				return new CommandClassPresentation(MarkerClassKind.Other, LocalizedClassLabel(MarkerClassKind.Other, russian), exactClass: false);
			}
			return new CommandClassPresentation(markerClassKind, LocalizedClassLabel(markerClassKind, russian), exactClass: true);
		}

		public static string LocalizedSemanticClassLabel(MarkerClassKind kind, bool russian)
		{
			if (russian)
			{
				return kind switch
				{
					MarkerClassKind.Tier1 => "Белый", 
					MarkerClassKind.Tier2 => "Зелёный", 
					MarkerClassKind.Tier3 => "Красный", 
					MarkerClassKind.Boss => "Жёлтый", 
					MarkerClassKind.Lunar => "Лунный", 
					MarkerClassKind.Void => "Предмет Бездны", 
					MarkerClassKind.Equipment => "Снаряжение", 
					MarkerClassKind.LunarEquipment => "Лунное снаряжение", 
					_ => "Выбор предмета", 
				};
			}
			return kind switch
			{
				MarkerClassKind.Tier1 => "White", 
				MarkerClassKind.Tier2 => "Green", 
				MarkerClassKind.Tier3 => "Red", 
				MarkerClassKind.Boss => "Yellow", 
				MarkerClassKind.Lunar => "Lunar", 
				MarkerClassKind.Void => "Void", 
				MarkerClassKind.Equipment => "Equipment", 
				MarkerClassKind.LunarEquipment => "Lunar equipment", 
				_ => "Item choice", 
			};
		}

		public static CommandClassPresentation ResolveCommandClassForPresentation(IEnumerable<MarkerClassKind>? choiceClasses, bool russian)
		{
			if (choiceClasses == null)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedSemanticClassLabel(MarkerClassKind.Unknown, russian), exactClass: false);
			}
			MarkerClassKind[] array = choiceClasses.ToArray();
			if (array.Length == 0 || array.Any((MarkerClassKind x) => x == MarkerClassKind.Unknown))
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedSemanticClassLabel(MarkerClassKind.Unknown, russian), exactClass: false);
			}
			MarkerClassKind[] array2 = array.Distinct().ToArray();
			if (array2.Length != 1)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedSemanticClassLabel(MarkerClassKind.Unknown, russian), exactClass: false);
			}
			MarkerClassKind markerClassKind = array2[0];
			if (markerClassKind == MarkerClassKind.Other)
			{
				return new CommandClassPresentation(MarkerClassKind.Other, LocalizedSemanticClassLabel(MarkerClassKind.Other, russian), exactClass: false);
			}
			return new CommandClassPresentation(markerClassKind, LocalizedSemanticClassLabel(markerClassKind, russian), exactClass: true);
		}

		public static string LocalizedReadableClassLabel(MarkerClassKind kind, bool russian)
		{
			return LocalizedReadableClassLabel(kind, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static string LocalizedReadableClassLabel(MarkerClassKind kind, MarkerLanguage language)
		{
			return MarkerTextLocalization.ReadableClassLabel(kind, language);
		}

		public static CommandClassPresentation ResolveCommandClassForReadablePresentation(IEnumerable<MarkerClassKind>? choiceClasses, bool russian)
		{
			return ResolveCommandClassForReadablePresentation(choiceClasses, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static CommandClassPresentation ResolveCommandClassForReadablePresentation(IEnumerable<MarkerClassKind>? choiceClasses, MarkerLanguage language)
		{
			if (choiceClasses == null)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedReadableClassLabel(MarkerClassKind.Unknown, language), exactClass: false);
			}
			bool flag = false;
			MarkerClassKind markerClassKind = MarkerClassKind.Unknown;
			foreach (MarkerClassKind choiceClass in choiceClasses)
			{
				if (choiceClass == MarkerClassKind.Unknown)
				{
					return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedReadableClassLabel(MarkerClassKind.Unknown, language), exactClass: false);
				}
				if (!flag)
				{
					flag = true;
					markerClassKind = choiceClass;
				}
				else if (choiceClass != markerClassKind)
				{
					return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedReadableClassLabel(MarkerClassKind.Unknown, language), exactClass: false);
				}
			}
			if (!flag)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedReadableClassLabel(MarkerClassKind.Unknown, language), exactClass: false);
			}
			if (markerClassKind == MarkerClassKind.Other)
			{
				return new CommandClassPresentation(MarkerClassKind.Other, LocalizedReadableClassLabel(MarkerClassKind.Other, language), exactClass: false);
			}
			return new CommandClassPresentation(markerClassKind, LocalizedReadableClassLabel(markerClassKind, language), exactClass: true);
		}
	}
	public enum MarkerPresentationMode
	{
		Detailed,
		Compact
	}
	public enum MarkerCompactMixedStyle
	{
		NeutralSingleDiamond,
		CategoryDiamonds,
		CategoryDiamondPyramid
	}
	public enum MarkerCountRenderSource
	{
		None,
		TotalCountText,
		CategorySubcounts,
		DetailedCategoryRows
	}
	public enum MarkerPresentationGlyphKind
	{
		Diamond,
		Clock
	}
	public readonly struct MarkerPresentationSettings
	{
		public MarkerPresentationMode Mode { get; }

		public bool ShowDistance { get; }

		public float Scale { get; }

		public int DetailRows { get; }

		public bool ShowCategoryDiamond { get; }

		public bool ShowTierComposition { get; }

		public bool CompactShowCount { get; }

		public MarkerCompactMixedStyle CompactMixedStyle { get; }

		public MarkerCategorySortOrder CategorySortOrder { get; }

		public bool UseCategorySummaryPresentation { get; }

		public MarkerPresentationSettings(MarkerPresentationMode mode, bool showDistance, float scale, int detailRows)
			: this(mode, showDistance, scale, detailRows, showCategoryDiamond: true, showTierComposition: true, compactShowCount: true, MarkerCompactMixedStyle.NeutralSingleDiamond, MarkerCategorySortOrder.HighToLow, useCategorySummaryPresentation: false)
		{
		}

		public MarkerPresentationSettings(MarkerPresentationMode mode, bool showDistance, float scale, int detailRows, bool showCategoryDiamond, bool showTierComposition, bool compactShowCount, MarkerCompactMixedStyle compactMixedStyle)
			: this(mode, showDistance, scale, detailRows, showCategoryDiamond, showTierComposition, compactShowCount, compactMixedStyle, MarkerCategorySortOrder.HighToLow, useCategorySummaryPresentation: false)
		{
		}

		public MarkerPresentationSettings(MarkerPresentationMode mode, bool showDistance, float scale, int detailRows, bool showCategoryDiamond, bool showTierComposition, bool compactShowCount, MarkerCompactMixedStyle compactMixedStyle, MarkerCategorySortOrder categorySortOrder)
			: this(mode, showDistance, scale, detailRows, showCategoryDiamond, showTierComposition, compactShowCount, compactMixedStyle, categorySortOrder, useCategorySummaryPresentation: true)
		{
		}

		private MarkerPresentationSettings(MarkerPresentationMode mode, bool showDistance, float scale, int detailRows, bool showCategoryDiamond, bool showTierComposition, bool compactShowCount, MarkerCompactMixedStyle compactMixedStyle, MarkerCategorySortOrder categorySortOrder, bool useCategorySummaryPresentation)
		{
			Mode = mode;
			ShowDistance = showDistance;
			Scale = MarkerClusterPresentationPolicy.ClampMarkerScale(scale);
			DetailRows = MarkerClusterPresentationPolicy.ClampDetailRows(detailRows);
			ShowCategoryDiamond = showCategoryDiamond;
			ShowTierComposition = showTierComposition;
			CompactShowCount = compactShowCount;
			CompactMixedStyle = compactMixedStyle;
			CategorySortOrder = categorySortOrder;
			UseCategorySummaryPresentation = useCategorySummaryPresentation;
		}
	}
	public readonly struct MarkerCompactCategoryBadge
	{
		public MarkerSemanticCategory Category { get; }

		public int Count { get; }

		public int DisplayPriority { get; }

		public MarkerLifetimeKind Lifetime { get; }

		public MarkerPresentationGlyphKind GlyphKind { get; }

		public MarkerLifetimeIndicatorSpec LifetimeIndicator { get; }

		public float PyramidVerticalOffsetUnits => MarkerCategorySummaryPolicy.PyramidVerticalOffsetUnits(Category);

		public MarkerCompactCategoryBadge(MarkerSemanticCategory category, int count)
			: this(category, count, MarkerCategorySummaryPolicy.DisplayPriority(category), MarkerLifetimeKind.Permanent, MarkerPresentationGlyphKind.Diamond)
		{
		}

		public MarkerCompactCategoryBadge(MarkerSemanticCategory category, int count, int displayPriority)
			: this(category, count, displayPriority, MarkerLifetimeKind.Permanent, MarkerPresentationGlyphKind.Diamond)
		{
		}

		public MarkerCompactCategoryBadge(MarkerSemanticCategory category, int count, int displayPriority, MarkerLifetimeIndicatorSpec lifetimeIndicator)
			: this(category, count, displayPriority, lifetimeIndicator.Visible ? MarkerLifetimeKind.Temporary : MarkerLifetimeKind.Permanent, lifetimeIndicator.Visible ? MarkerPresentationGlyphKind.Clock : MarkerPresentationGlyphKind.Diamond)
		{
		}

		public MarkerCompactCategoryBadge(MarkerSemanticCategory category, int count, int displayPriority, MarkerLifetimeKind lifetime, MarkerPresentationGlyphKind glyphKind)
		{
			Category = category;
			Count = Math.Max(0, count);
			DisplayPriority = displayPriority;
			Lifetime = lifetime;
			GlyphKind = glyphKind;
			LifetimeIndicator = MarkerLifetimeIndicatorSpec.Hidden;
		}
	}
	public readonly struct MarkerDetailedItemRow
	{
		public string ItemIdentity { get; }

		public string LocalizedName { get; }

		public MarkerSemanticCategory Category { get; }

		public int Count { get; }

		public MarkerLifetimeKind Lifetime { get; }

		public MarkerPresentationGlyphKind GlyphKind { get; }

		public string DisplayLabel { get; }

		public MarkerLifetimeIndicatorSpec LifetimeIndicator { get; }

		public MarkerDetailedItemRow(string itemIdentity, string localizedName, MarkerSemanticCategory category, int count)
			: this(itemIdentity, localizedName, category, count, MarkerLifetimeKind.Permanent, localizedName)
		{
		}

		public MarkerDetailedItemRow(string itemIdentity, string localizedName, MarkerSemanticCategory category, int count, MarkerLifetimeKind lifetime, string displayLabel)
		{
			ItemIdentity = itemIdentity ?? string.Empty;
			LocalizedName = (string.IsNullOrWhiteSpace(localizedName) ? "Pickup" : localizedName);
			Category = category;
			Count = Math.Max(0, count);
			Lifetime = lifetime;
			GlyphKind = ((lifetime == MarkerLifetimeKind.Temporary) ? MarkerPresentationGlyphKind.Clock : MarkerPresentationGlyphKind.Diamond);
			DisplayLabel = (string.IsNullOrWhiteSpace(displayLabel) ? LocalizedName : displayLabel);
			LifetimeIndicator = MarkerLifetimePolicy.BuildIndicator(lifetime, (lifetime == MarkerLifetimeKind.Temporary) ? Count : 0, (lifetime == MarkerLifetimeKind.Mixed) ? Count : 0, (lifetime == MarkerLifetimeKind.Unknown) ? Count : 0, allowCount: false, showSingleCountWhenMixed: false);
		}
	}
	public sealed class MarkerClusterPresentationPlan
	{
		public string Text { get; }

		public IReadOnlyList<MarkerCompactCategoryBadge> CompactBadges { get; }

		public IReadOnlyList<MarkerCompactCategoryBadge> CategoryEntries => CompactBadges;

		public IReadOnlyList<MarkerDetailedItemRow> DetailedItemRows { get; }

		public int TotalCount { get; }

		public int ShownDetailRows { get; }

		public int OverflowPhysicalCount { get; }

		public bool Expanded { get; }

		public bool NeutralMainSemantic { get; }

		public MarkerCountRenderSource CountRenderSource { get; }

		public bool ShowMainDiamond { get; }

		public bool ShowDetailedCategoryRowDiamonds { get; }

		public bool ShowCompactCategoryDiamonds { get; }

		public MarkerSemanticCategory MainCategory { get; }

		public MarkerLifetimeIndicatorSpec LifetimeIndicator { get; private set; }

		public bool RenderCategorySubcounts => CountRenderSource == MarkerCountRenderSource.CategorySubcounts;

		public bool RenderTotalCount => CountRenderSource == MarkerCountRenderSource.TotalCountText;

		internal MarkerClusterPresentationPlan(string text, MarkerCompactCategoryBadge[] compactBadges, int totalCount, int shownDetailRows, int overflowPhysicalCount, bool expanded, bool neutralMainSemantic, MarkerCountRenderSource countRenderSource, bool showMainDiamond, bool showDetailedCategoryRowDiamonds, bool showCompactCategoryDiamonds, MarkerSemanticCategory mainCategory)
			: this(text, compactBadges, Array.Empty<MarkerDetailedItemRow>(), totalCount, shownDetailRows, overflowPhysicalCount, expanded, neutralMainSemantic, countRenderSource, showMainDiamond, showDetailedCategoryRowDiamonds, showCompactCategoryDiamonds, mainCategory)
		{
		}

		internal MarkerClusterPresentationPlan(string text, MarkerCompactCategoryBadge[] compactBadges, MarkerDetailedItemRow[] detailedItemRows, int totalCount, int shownDetailRows, int overflowPhysicalCount, bool expanded, bool neutralMainSemantic, MarkerCountRenderSource countRenderSource, bool showMainDiamond, bool showDetailedCategoryRowDiamonds, bool showCompactCategoryDiamonds, MarkerSemanticCategory mainCategory)
		{
			Text = text ?? string.Empty;
			CompactBadges = compactBadges ?? Array.Empty<MarkerCompactCategoryBadge>();
			DetailedItemRows = detailedItemRows ?? Array.Empty<MarkerDetailedItemRow>();
			TotalCount = Math.Max(0, totalCount);
			ShownDetailRows = Math.Max(0, shownDetailRows);
			OverflowPhysicalCount = Math.Max(0, overflowPhysicalCount);
			Expanded = expanded;
			NeutralMainSemantic = neutralMainSemantic;
			CountRenderSource = countRenderSource;
			ShowMainDiamond = showMainDiamond;
			ShowDetailedCategoryRowDiamonds = showDetailedCategoryRowDiamonds;
			ShowCompactCategoryDiamonds = showCompactCategoryDiamonds;
			MainCategory = mainCategory;
			LifetimeIndicator = MarkerLifetimeIndicatorSpec.Hidden;
		}

		internal void SetLifetimeIndicator(MarkerLifetimeIndicatorSpec lifetimeIndicator)
		{
			LifetimeIndicator = lifetimeIndicator;
		}
	}
	public static class MarkerClusterPresentationPolicy
	{
		public const int TOTAL_COUNT_RENDER_SLOTS_PER_PRESENTATION_NODE = 1;

		public const float MarkerScaleMin = 0.75f;

		public const float MarkerScaleMax = 1.25f;

		public const float MarkerScaleDefault = 1f;

		public const int MarkerDetailRowsMin = 1;

		public const int MarkerDetailRowsMax = 12;

		public const int MarkerDetailRowsDefault = 5;

		public const int DetailedCompositionLineCharacterBudget = 48;

		public const int MaxCompositionLines = 2;

		public const int MaxCompactCategoryBadges = 14;

		public const int MaxCompactLifetimePresentationGroups = 28;

		public const float DetailedItemLabelMaxWidth1080 = 420f;

		public const float DetailedItemLabelMinWidth1080 = 180f;

		public static float ClampMarkerScale(float value)
		{
			if (float.IsNaN(value) || float.IsInfinity(value))
			{
				return 1f;
			}
			if (value < 0.75f)
			{
				return 0.75f;
			}
			if (!(value > 1.25f))
			{
				return value;
			}
			return 1.25f;
		}

		public static int ClampDetailRows(int value)
		{
			if (value < 1)
			{
				return 1;
			}
			if (value <= 12)
			{
				return value;
			}
			return 12;
		}

		public static float BuildDetailedItemLabelWidthLimit(float screenWidth, float screenHeight, float markerScale)
		{
			float num = ((float.IsNaN(screenWidth) || float.IsInfinity(screenWidth) || screenWidth <= 0f) ? 1920f : screenWidth);
			float num2 = ((float.IsNaN(screenHeight) || float.IsInfinity(screenHeight) || screenHeight <= 0f) ? 1080f : screenHeight);
			float num3 = Math.Min(num / 1920f, num2 / 1080f);
			if (num3 <= 0f || float.IsNaN(num3) || float.IsInfinity(num3))
			{
				num3 = 1f;
			}
			float num4 = ClampMarkerScale(markerScale);
			float val = 420f * num3 * num4;
			float val2 = 180f * num3 * num4;
			float val3 = num * 0.34f;
			return Math.Max(val2, Math.Min(val, val3));
		}

		public static MarkerClusterPresentationPlan Build(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, bool expanded, bool russian)
		{
			return Build(cluster, settings, distanceMeters, expanded, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static MarkerClusterPresentationPlan Build(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, bool expanded, MarkerLanguage language)
		{
			if (cluster == null)
			{
				throw new ArgumentNullException("cluster");
			}
			MarkerClusterPresentationPlan markerClusterPresentationPlan = ((!settings.UseCategorySummaryPresentation) ? ((settings.Mode == MarkerPresentationMode.Compact) ? BuildCompactLegacy(cluster, settings, distanceMeters, expanded, language) : BuildDetailedLegacy(cluster, settings, distanceMeters, expanded, language)) : ((settings.Mode == MarkerPresentationMode.Compact) ? BuildCompactCategoryPyramid(cluster, settings, distanceMeters, language) : BuildDetailedCategorySummary(cluster, settings, distanceMeters, language)));
			if ((settings.Mode == MarkerPresentationMode.Compact && !markerClusterPresentationPlan.ShowCompactCategoryDiamonds) || (settings.Mode == MarkerPresentationMode.Detailed && markerClusterPresentationPlan.DetailedItemRows.Count == 0 && !markerClusterPresentationPlan.ShowDetailedCategoryRowDiamonds))
			{
				markerClusterPresentationPlan.SetLifetimeIndicator(BuildClusterLifetimeIndicator(cluster, settings.Mode == MarkerPresentationMode.Compact && settings.CompactShowCount, showSingleCountWhenMixed: true));
			}
			return markerClusterPresentationPlan;
		}

		public static MarkerClusterPresentationPlan BuildOffscreen(int nearestDistanceMeters, int sectorTotalCount, bool showDistance, bool showTotalCount, bool russian)
		{
			return BuildOffscreen(nearestDistanceMeters, sectorTotalCount, showDistance, showTotalCount, MarkerTextLocalization.FromRussianCompatibility(russian), MarkerLifetimeKind.Permanent, 0, 0, 0);
		}

		public static MarkerClusterPresentationPlan BuildOffscreen(int nearestDistanceMeters, int sectorTotalCount, bool showDistance, bool showTotalCount, MarkerLanguage language)
		{
			return BuildOffscreen(nearestDistanceMeters, sectorTotalCount, showDistance, showTotalCount, language, MarkerLifetimeKind.Permanent, 0, 0, 0);
		}

		public static MarkerClusterPresentationPlan BuildOffscreen(int nearestDistanceMeters, int sectorTotalCount, bool showDistance, bool showTotalCount, bool russian, MarkerLifetimeKind lifetime, int temporaryPhysicalMembers, int mixedLifetimeMembers, int unknownLifetimeMembers)
		{
			return BuildOffscreen(nearestDistanceMeters, sectorTotalCount, showDistance, showTotalCount, MarkerTextLocalization.FromRussianCompatibility(russian), lifetime, temporaryPhysicalMembers, mixedLifetimeMembers, unknownLifetimeMembers);
		}

		public static MarkerClusterPresentationPlan BuildOffscreen(int nearestDistanceMeters, int sectorTotalCount, bool showDistance, bool showTotalCount, MarkerLanguage language, MarkerLifetimeKind lifetime, int temporaryPhysicalMembers, int mixedLifetimeMembers, int unknownLifetimeMembers)
		{
			StringBuilder stringBuilder = new StringBuilder(32);
			MarkerCountRenderSource countRenderSource = MarkerCountRenderSource.None;
			if (showTotalCount)
			{
				stringBuilder.Append('×').Append(Math.Max(0, sectorTotalCount).ToString(CultureInfo.InvariantCulture));
				countRenderSource = MarkerCountRenderSource.TotalCountText;
			}
			if (showDistance)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append(Math.Max(0, nearestDistanceMeters).ToString(CultureInfo.InvariantCulture)).Append(" ").Append(MarkerTextLocalization.DistanceUnit(language));
			}
			MarkerClusterPresentationPlan markerClusterPresentationPlan = new MarkerClusterPresentationPlan(stringBuilder.ToString(), Array.Empty<MarkerCompactCategoryBadge>(), Math.Max(0, sectorTotalCount), 0, 0, expanded: false, neutralMainSemantic: true, countRenderSource, showMainDiamond: true, showDetailedCategoryRowDiamonds: false, showCompactCategoryDiamonds: false, MarkerSemanticCategory.Unknown);
			markerClusterPresentationPlan.SetLifetimeIndicator((lifetime == MarkerLifetimeKind.Temporary) ? MarkerLifetimePolicy.BuildIndicator(MarkerLifetimeKind.Temporary, temporaryPhysicalMembers, 0, 0, showTotalCount, showSingleCountWhenMixed: false) : MarkerLifetimeIndicatorSpec.Hidden);
			return markerClusterPresentationPlan;
		}

		public static string LocalizedCategoryPlural(MarkerSemanticCategory category, bool russian)
		{
			return LocalizedCategoryPlural(category, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static string LocalizedCategoryPlural(MarkerSemanticCategory category, MarkerLanguage language)
		{
			return MarkerTextLocalization.CategoryPlural(category, language);
		}

		public static string LocalizedCompositionWord(MarkerSemanticCategory category, bool russian)
		{
			return LocalizedCompositionWord(category, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static string LocalizedCompositionWord(MarkerSemanticCategory category, MarkerLanguage language)
		{
			return MarkerTextLocalization.CompositionLabel(category, language);
		}

		public static int CompositionCountSum(IReadOnlyList<MarkerCategoryCount> composition)
		{
			if (composition == null)
			{
				throw new ArgumentNullException("composition");
			}
			int num = 0;
			for (int i = 0; i < composition.Count; i++)
			{
				num += Math.Max(0, composition[i].Count);
			}
			return num;
		}

		public static string LocalizedCategorySummaryLabel(MarkerSemanticCategory category, bool russian)
		{
			return LocalizedCategorySummaryLabel(category, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static string LocalizedCategorySummaryLabel(MarkerSemanticCategory category, MarkerLanguage language)
		{
			return MarkerTextLocalization.CategorySummaryLabel(category, language);
		}

		private static MarkerClusterPresentationPlan BuildDetailedCategorySummary(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, MarkerLanguage language)
		{
			if (!IsCommandChoiceCluster(cluster))
			{
				return BuildDetailedOrdinaryItemSummary(cluster, settings, distanceMeters, language);
			}
			return BuildDetailedCommandCategorySummary(cluster, settings, distanceMeters, language);
		}

		private static MarkerClusterPresentationPlan BuildDetailedCommandCategorySummary(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, MarkerLanguage language)
		{
			StringBuilder stringBuilder = new StringBuilder(160);
			int totalCount = cluster.TotalCount;
			bool flag = cluster.IsMixedCategory || cluster.HomogeneousCategory == MarkerSemanticCategory.Unknown || cluster.HomogeneousCategory == MarkerSemanticCategory.CommandState;
			MarkerSemanticCategory mainCategory = (flag ? MarkerSemanticCategory.Unknown : cluster.HomogeneousCategory);
			MarkerCompactCategoryBadge[] array = BuildCategoryEntriesWithLifetime(cluster, settings.CategorySortOrder);
			if (totalCount <= 1 && IsTruthfulConcreteSingleAggregate(cluster))
			{
				stringBuilder.Append(cluster.ItemRows[0].LocalizedName).Append(" ×").Append(totalCount.ToString(CultureInfo.InvariantCulture));
				AppendDistance(stringBuilder, settings.ShowDistance, distanceMeters, language);
				return new MarkerClusterPresentationPlan(stringBuilder.ToString(), array, totalCount, 0, 0, expanded: false, flag, MarkerCountRenderSource.TotalCountText, settings.ShowCategoryDiamond, showDetailedCategoryRowDiamonds: false, showCompactCategoryDiamonds: false, mainCategory);
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append(LocalizedCategorySummaryLabel(array[i].Category, language)).Append(" ×").Append(array[i].Count.ToString(CultureInfo.InvariantCulture));
			}
			AppendDistance(stringBuilder, settings.ShowDistance, distanceMeters, language);
			return new MarkerClusterPresentationPlan(stringBuilder.ToString(), array, totalCount, 0, 0, expanded: false, flag, MarkerCountRenderSource.DetailedCategoryRows, showMainDiamond: false, settings.ShowCategoryDiamond, showCompactCategoryDiamonds: false, mainCategory);
		}

		private static MarkerClusterPresentationPlan BuildDetailedOrdinaryItemSummary(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, MarkerLanguage language)
		{
			List<MarkerDetailedItemRow> list = new List<MarkerDetailedItemRow>(cluster.ItemRows.Count);
			for (int i = 0; i < cluster.ItemRows.Count; i++)
			{
				MarkerItemAggregate markerItemAggregate = cluster.ItemRows[i];
				if (markerItemAggregate.Count > 0)
				{
					list.Add(new MarkerDetailedItemRow(markerItemAggregate.ItemIdentity, markerItemAggregate.LocalizedName, markerItemAggregate.Category, markerItemAggregate.Count, markerItemAggregate.Lifetime, MarkerLifetimePolicy.BuildDetailedItemDisplayName(string.IsNullOrWhiteSpace(markerItemAggregate.LocalizedName) ? MarkerTextLocalization.FallbackPickup(language) : markerItemAggregate.LocalizedName, markerItemAggregate.Lifetime, language == MarkerLanguage.Russian)));
				}
			}
			list.Sort((MarkerDetailedItemRow left, MarkerDetailedItemRow right) => CompareDetailedItems(left, right, settings.CategorySortOrder));
			int num = Math.Min(settings.DetailRows, list.Count);
			int num2 = Math.Max(0, list.Count - num);
			StringBuilder stringBuilder = new StringBuilder(192);
			for (int num3 = 0; num3 < num; num3++)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append(list[num3].DisplayLabel).Append(" ×").Append(list[num3].Count.ToString(CultureInfo.InvariantCulture));
			}
			if (num2 > 0)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append(BuildDetailedOverflowText(num2, language));
			}
			AppendDistance(stringBuilder, settings.ShowDistance, distanceMeters, language);
			MarkerDetailedItemRow[] array = new MarkerDetailedItemRow[num];
			for (int num4 = 0; num4 < num; num4++)
			{
				array[num4] = list[num4];
			}
			bool flag = cluster.IsMixedCategory || cluster.HomogeneousCategory == MarkerSemanticCategory.Unknown;
			MarkerSemanticCategory mainCategory = (flag ? MarkerSemanticCategory.Unknown : cluster.HomogeneousCategory);
			return new MarkerClusterPresentationPlan(stringBuilder.ToString(), Array.Empty<MarkerCompactCategoryBadge>(), array, cluster.TotalCount, num, num2, expanded: false, flag, MarkerCountRenderSource.None, showMainDiamond: false, showDetailedCategoryRowDiamonds: false, showCompactCategoryDiamonds: false, mainCategory);
		}

		public static string BuildDetailedOverflowText(int hiddenDistinctTypes, bool russian)
		{
			return BuildDetailedOverflowText(hiddenDistinctTypes, MarkerTextLocalization.FromRussianCompatibility(russian));
		}

		public static string BuildDetailedOverflowText(int hiddenDistinctTypes, MarkerLanguage language)
		{
			return MarkerTextLocalization.FormatMoreTypes(hiddenDistinctTypes, language);
		}

		public static string RussianDistinctTypeWord(int hiddenDistinctTypes)
		{
			return MarkerTextLocalization.RussianDistinctTypeWord(hiddenDistinctTypes);
		}

		private static int CompareDetailedItems(MarkerDetailedItemRow left, MarkerDetailedItemRow right, MarkerCategorySortOrder sortOrder)
		{
			int value = MarkerCategorySummaryPolicy.DisplayPriority(left.Category);
			int num = MarkerCategorySummaryPolicy.DisplayPriority(right.Category).CompareTo(value);
			if (sortOrder == MarkerCategorySortOrder.LowToHigh)
			{
				num = -num;
			}
			if (num != 0)
			{
				return num;
			}
			int num2 = string.Compare(left.LocalizedName, right.LocalizedName, StringComparison.Ordinal);
			if (num2 != 0)
			{
				return num2;
			}
			int num3 = string.Compare(left.ItemIdentity, right.ItemIdentity, StringComparison.Ordinal);
			if (num3 != 0)
			{
				return num3;
			}
			return MarkerLifetimePolicy.DetailedSortRank(left.Lifetime).CompareTo(MarkerLifetimePolicy.DetailedSortRank(right.Lifetime));
		}

		private static bool IsCommandChoiceCluster(MarkerSemanticCluster cluster)
		{
			if (cluster.ItemRows.Count == 0)
			{
				return cluster.HomogeneousCategory == MarkerSemanticCategory.CommandState;
			}
			for (int i = 0; i < cluster.ItemRows.Count; i++)
			{
				if (!(cluster.ItemRows[i].ItemIdentity ?? string.Empty).StartsWith("COMMAND:", StringComparison.OrdinalIgnoreCase))
				{
					return false;
				}
			}
			return true;
		}

		private static MarkerClusterPresentationPlan BuildCompactCategoryPyramid(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, MarkerLanguage language)
		{
			int totalCount = cluster.TotalCount;
			MarkerCompactCategoryBadge[] compactBadges = BuildCategoryEntriesWithLifetime(cluster, settings.CategorySortOrder);
			bool flag = cluster.IsMixedCategory || cluster.HomogeneousCategory == MarkerSemanticCategory.Unknown || cluster.HomogeneousCategory == MarkerSemanticCategory.CommandState;
			MarkerSemanticCategory mainCategory = (flag ? MarkerSemanticCategory.Unknown : cluster.HomogeneousCategory);
			StringBuilder stringBuilder = new StringBuilder(48);
			AppendDistance(stringBuilder, settings.ShowDistance, distanceMeters, language);
			return new MarkerClusterPresentationPlan(stringBuilder.ToString(), compactBadges, totalCount, 0, 0, expanded: false, flag, settings.CompactShowCount ? MarkerCountRenderSource.CategorySubcounts : MarkerCountRenderSource.None, showMainDiamond: false, showDetailedCategoryRowDiamonds: false, showCompactCategoryDiamonds: true, mainCategory);
		}

		private static MarkerClusterPresentationPlan BuildDetailedLegacy(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, bool expanded, MarkerLanguage language)
		{
			StringBuilder stringBuilder = new StringBuilder(192);
			int totalCount = cluster.TotalCount;
			bool flag = cluster.IsMixedCategory || cluster.HomogeneousCategory == MarkerSemanticCategory.Unknown || cluster.HomogeneousCategory == MarkerSemanticCategory.CommandState;
			MarkerSemanticCategory mainCategory = (flag ? MarkerSemanticCategory.Unknown : cluster.HomogeneousCategory);
			if (IsTruthfulConcreteSingleAggregate(cluster))
			{
				stringBuilder.Append(cluster.ItemRows[0].LocalizedName).Append(" ×").Append(totalCount.ToString(CultureInfo.InvariantCulture));
			}
			else if (cluster.IsHomogeneousCategory)
			{
				stringBuilder.Append(LocalizedCategoryPlural(cluster.HomogeneousCategory, language)).Append(" ×").Append(totalCount.ToString(CultureInfo.InvariantCulture));
			}
			else
			{
				stringBuilder.Append(MarkerTextLocalization.GenericItems(language)).Append(" ×").Append(totalCount.ToString(CultureInfo.InvariantCulture));
				if (settings.ShowTierComposition)
				{
					AppendDetailedComposition(stringBuilder, cluster.Composition, language);
				}
			}
			int shownRows = 0;
			int overflowPhysicalCount = 0;
			if (expanded && totalCount > 1)
			{
				AppendExpandedDetailRows(stringBuilder, cluster.ItemRows, settings.DetailRows, totalCount, language, out shownRows, out overflowPhysicalCount);
			}
			AppendDistance(stringBuilder, settings.ShowDistance, distanceMeters, language);
			return new MarkerClusterPresentationPlan(stringBuilder.ToString(), Array.Empty<MarkerCompactCategoryBadge>(), totalCount, shownRows, overflowPhysicalCount, expanded, flag, MarkerCountRenderSource.TotalCountText, settings.ShowCategoryDiamond, showDetailedCategoryRowDiamonds: false, showCompactCategoryDiamonds: false, mainCategory);
		}

		private static MarkerClusterPresentationPlan BuildCompactLegacy(MarkerSemanticCluster cluster, MarkerPresentationSettings settings, int distanceMeters, bool expanded, MarkerLanguage language)
		{
			int totalCount = cluster.TotalCount;
			MarkerCompactCategoryBadge[] compactBadges = BuildCategoryEntriesWithLifetime(cluster, MarkerCategorySortOrder.HighToLow, preserveCompositionOrder: true);
			bool flag = cluster.IsMixedCategory && settings.CompactMixedStyle == MarkerCompactMixedStyle.CategoryDiamonds;
			MarkerCountRenderSource markerCountRenderSource = ((!flag) ? (settings.CompactShowCount ? MarkerCountRenderSource.TotalCountText : MarkerCountRenderSource.None) : (settings.CompactShowCount ? MarkerCountRenderSource.CategorySubcounts : MarkerCountRenderSource.None));
			StringBuilder stringBuilder = new StringBuilder(160);
			if (markerCountRenderSource == MarkerCountRenderSource.TotalCountText)
			{
				stringBuilder.Append('×').Append(totalCount.ToString(CultureInfo.InvariantCulture));
			}
			int shownRows = 0;
			int overflowPhysicalCount = 0;
			if (expanded)
			{
				AppendExpandedDetailRows(stringBuilder, cluster.ItemRows, settings.DetailRows, totalCount, language, out shownRows, out overflowPhysicalCount);
			}
			AppendDistance(stringBuilder, settings.ShowDistance, distanceMeters, language);
			bool flag2 = cluster.IsMixedCategory || cluster.HomogeneousCategory == MarkerSemanticCategory.Unknown || cluster.HomogeneousCategory == MarkerSemanticCategory.CommandState;
			MarkerSemanticCategory mainCategory = (flag2 ? MarkerSemanticCategory.Unknown : cluster.HomogeneousCategory);
			return new MarkerClusterPresentationPlan(stringBuilder.ToString(), compactBadges, totalCount, shownRows, overflowPhysicalCount, expanded, flag2, markerCountRenderSource, !flag, showDetailedCategoryRowDiamonds: false, flag, mainCategory);
		}

		private static bool IsTruthfulConcreteSingleAggregate(MarkerSemanticCluster cluster)
		{
			if (cluster.ItemRows.Count != 1 || !cluster.IsHomogeneousCategory)
			{
				return false;
			}
			if (cluster.HomogeneousCategory == MarkerSemanticCategory.CommandState || cluster.HomogeneousCategory == MarkerSemanticCategory.Unknown)
			{
				return false;
			}
			string text = cluster.ItemRows[0].ItemIdentity ?? string.Empty;
			if (!text.StartsWith("COMMAND:", StringComparison.OrdinalIgnoreCase))
			{
				return !text.StartsWith("UNKNOWN:", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private static void AppendExpandedDetailRows(StringBuilder builder, IReadOnlyList<MarkerItemAggregate> itemRows, int requestedRows, int totalPhysicalCount, MarkerLanguage language, out int shownRows, out int overflowPhysicalCount)
		{
			int num = Math.Min(ClampDetailRows(requestedRows), 12);
			Span<int> span = stackalloc int[12];
			for (int i = 0; i < span.Length; i++)
			{
				span[i] = -1;
			}
			int num2 = 0;
			for (int j = 0; j < itemRows.Count; j++)
			{
				MarkerItemAggregate left = itemRows[j];
				if (left.Count <= 0)
				{
					continue;
				}
				int num3 = num2;
				for (int k = 0; k < num2; k++)
				{
					if (CompareExpandedDetailPriority(left, itemRows[span[k]]) < 0)
					{
						num3 = k;
						break;
					}
				}
				if (num3 < num)
				{
					if (num2 < num)
					{
						num2++;
					}
					for (int num4 = num2 - 1; num4 > num3; num4--)
					{
						span[num4] = span[num4 - 1];
					}
					span[num3] = j;
				}
			}
			int num5 = 0;
			for (int l = 0; l < num2; l++)
			{
				MarkerItemAggregate markerItemAggregate = itemRows[span[l]];
				if (builder.Length > 0)
				{
					builder.Append('\n');
				}
				builder.Append(markerItemAggregate.LocalizedName);
				if (markerItemAggregate.Count > 1)
				{
					builder.Append(" ×").Append(markerItemAggregate.Count.ToString(CultureInfo.InvariantCulture));
				}
				num5 += markerItemAggregate.Count;
			}
			shownRows = num2;
			overflowPhysicalCount = Math.Max(0, totalPhysicalCount - num5);
			if (overflowPhysicalCount > 0)
			{
				if (builder.Length > 0)
				{
					builder.Append('\n');
				}
				builder.Append(MarkerTextLocalization.FormatPhysicalItems(overflowPhysicalCount, language));
			}
		}

		private static int CompareExpandedDetailPriority(MarkerItemAggregate left, MarkerItemAggregate right)
		{
			int num = right.Count.CompareTo(left.Count);
			if (num != 0)
			{
				return num;
			}
			int num2 = MarkerSemanticCategoryPolicy.StableOrder(left.Category).CompareTo(MarkerSemanticCategoryPolicy.StableOrder(right.Category));
			if (num2 != 0)
			{
				return num2;
			}
			int num3 = string.Compare(left.LocalizedName, right.LocalizedName, StringComparison.Ordinal);
			if (num3 != 0)
			{
				return num3;
			}
			return string.Compare(left.ItemIdentity, right.ItemIdentity, StringComparison.Ordinal);
		}

		private static void AppendDetailedComposition(StringBuilder builder, IReadOnlyList<MarkerCategoryCount> composition, MarkerLanguage language)
		{
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < composition.Count; i++)
			{
				MarkerCategoryCount markerCategoryCount = composition[i];
				if (markerCategoryCount.Count > 0)
				{
					string text = LocalizedCompositionWord(markerCategoryCount.Category, language) + " " + markerCategoryCount.Count.ToString(CultureInfo.InvariantCulture);
					int num3 = ((num != 0) ? 3 : 0);
					if (num > 0 && num + num3 + text.Length > 48 && num2 + 1 < 2)
					{
						builder.Append('\n');
						num = 0;
						num2++;
						num3 = 0;
					}
					else if (num == 0)
					{
						builder.Append('\n');
					}
					if (num > 0)
					{
						builder.Append(" · ");
					}
					builder.Append(text);
					num += num3 + text.Length;
				}
			}
		}

		private static MarkerCompactCategoryBadge[] BuildCategoryEntriesWithLifetime(MarkerSemanticCluster cluster, MarkerCategorySortOrder sortOrder, bool preserveCompositionOrder = false)
		{
			MarkerCompactCategoryBadge[] array;
			if (preserveCompositionOrder)
			{
				int num = 0;
				for (int i = 0; i < cluster.Composition.Count; i++)
				{
					if (num >= 14)
					{
						break;
					}
					if (cluster.Composition[i].Count > 0)
					{
						num++;
					}
				}
				array = new MarkerCompactCategoryBadge[num];
				int num2 = 0;
				for (int j = 0; j < cluster.Composition.Count; j++)
				{
					if (num2 >= array.Length)
					{
						break;
					}
					MarkerCategoryCount markerCategoryCount = cluster.Composition[j];
					if (markerCategoryCount.Count > 0)
					{
						array[num2++] = new MarkerCompactCategoryBadge(markerCategoryCount.Category, markerCategoryCount.Count, MarkerCategorySummaryPolicy.DisplayPriority(markerCategoryCount.Category));
					}
				}
			}
			else
			{
				array = MarkerCategorySummaryPolicy.BuildCategoryEntries(cluster.Composition, sortOrder);
			}
			if (array.Length == 0)
			{
				return array;
			}
			List<MarkerCompactCategoryBadge> list = new List<MarkerCompactCategoryBadge>(Math.Min(28, array.Length * 2));
			for (int k = 0; k < array.Length; k++)
			{
				if (list.Count >= 28)
				{
					break;
				}
				MarkerCompactCategoryBadge markerCompactCategoryBadge = array[k];
				int num3 = 0;
				int num4 = 0;
				int num5 = 0;
				for (int l = 0; l < cluster.ItemRows.Count; l++)
				{
					MarkerItemAggregate markerItemAggregate = cluster.ItemRows[l];
					if (markerItemAggregate.Category == markerCompactCategoryBadge.Category && markerItemAggregate.Count > 0)
					{
						switch (markerItemAggregate.Lifetime)
						{
						case MarkerLifetimeKind.Temporary:
							num3 += markerItemAggregate.Count;
							break;
						case MarkerLifetimeKind.Permanent:
							num4 += markerItemAggregate.Count;
							break;
						default:
							num5 += markerItemAggregate.Count;
							break;
						}
					}
				}
				int num6 = Math.Max(0, num4 + num5);
				if (num6 > 0 && list.Count < 28)
				{
					MarkerLifetimeKind lifetime = ((num5 != 0) ? MarkerLifetimeKind.Unknown : MarkerLifetimeKind.Permanent);
					list.Add(new MarkerCompactCategoryBadge(markerCompactCategoryBadge.Category, num6, markerCompactCategoryBadge.DisplayPriority, lifetime, MarkerPresentationGlyphKind.Diamond));
				}
				if (num3 > 0 && list.Count < 28)
				{
					list.Add(new MarkerCompactCategoryBadge(markerCompactCategoryBadge.Category, num3, markerCompactCategoryBadge.DisplayPriority, MarkerLifetimeKind.Temporary, MarkerPresentationGlyphKind.Clock));
				}
			}
			return list.ToArray();
		}

		private static MarkerLifetimeIndicatorSpec BuildClusterLifetimeIndicator(MarkerSemanticCluster cluster, bool allowCount, bool showSingleCountWhenMixed)
		{
			return MarkerLifetimePolicy.BuildIndicator(cluster.LifetimeSummary, cluster.TemporaryPhysicalMemberCount, cluster.MixedLifetimeMemberCount, cluster.UnknownLifetimeMemberCount, allowCount, showSingleCountWhenMixed);
		}

		private static void AppendDistance(StringBuilder builder, bool showDistance, int distanceMeters, MarkerLanguage language)
		{
			if (showDistance)
			{
				if (builder.Length > 0)
				{
					builder.Append('\n');
				}
				builder.Append(Math.Max(0, distanceMeters).ToString(CultureInfo.InvariantCulture)).Append(" ").Append(MarkerTextLocalization.DistanceUnit(language));
			}
		}
	}
	public sealed class MarkerDenseAreaPresentationNode
	{
		public long StableKey { get; }

		public bool IsDenseSummary { get; }

		public IReadOnlyList<long> PhysicalClusterKeys { get; }

		public MarkerSemanticCluster PresentationCluster { get; }

		public MarkerWorldPoint WorldAnchor => PresentationCluster.WorldAnchor;

		public IReadOnlyList<long> MemberStableKeys => PresentationCluster.MemberStableKeys;

		public int TotalCount => PresentationCluster.TotalCount;

		public string MemberFingerprint => PresentationCluster.MemberFingerprint;

		internal MarkerDenseAreaPresentationNode(long stableKey, bool isDenseSummary, long[] physicalClusterKeys, MarkerSemanticCluster presentationCluster)
		{
			StableKey = stableKey;
			IsDenseSummary = isDenseSummary;
			PhysicalClusterKeys = physicalClusterKeys ?? Array.Empty<long>();
			PresentationCluster = presentationCluster ?? throw new ArgumentNullException("presentationCluster");
		}
	}
	public sealed class MarkerDenseAreaUpdate
	{
		public IReadOnlyList<MarkerDenseAreaPresentationNode> Nodes { get; }

		public bool MembershipChanged { get; }

		internal MarkerDenseAreaUpdate(IReadOnlyList<MarkerDenseAreaPresentationNode> nodes, bool membershipChanged)
		{
			Nodes = nodes;
			MembershipChanged = membershipChanged;
		}
	}
	public sealed class MarkerDenseAreaSummaryTracker
	{
		private readonly struct PairKey : IEquatable<PairKey>
		{
			public long A { get; }

			public long B { get; }

			public PairKey(long a, long b)
			{
				if (a <= b)
				{
					A = a;
					B = b;
				}
				else
				{
					A = b;
					B = a;
				}
			}

			public bool Equals(PairKey other)
			{
				if (A == other.A)
				{
					return B == other.B;
				}
				return false;
			}

			public override bool Equals(object? obj)
			{
				if (obj is PairKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (A.GetHashCode() * 397) ^ B.GetHashCode();
			}
		}

		private sealed class PairState
		{
			public bool Linked;

			public bool Pending;

			public bool PendingTarget;

			public double PendingSince;
		}

		private sealed class PreviousDenseOwner
		{
			public long OwnerKey { get; }

			public long[] MemberKeys { get; }

			public PreviousDenseOwner(long ownerKey, long[] memberKeys)
			{
				OwnerKey = ownerKey;
				MemberKeys = memberKeys;
			}
		}

		private sealed class MutableAggregate
		{
			public string ItemIdentity { get; }

			public string LocalizedName { get; }

			public MarkerSemanticCategory Category { get; }

			public MarkerLifetimeKind Lifetime { get; }

			public int Count { get; set; }

			public MutableAggregate(string itemIdentity, string localizedName, MarkerSemanticCategory category, MarkerLifetimeKind lifetime)
			{
				ItemIdentity = itemIdentity;
				LocalizedName = localizedName;
				Category = category;
				Lifetime = lifetime;
			}
		}

		public const float MergeRadiusMeters = 12f;

		public const float SplitRadiusMeters = 16f;

		public const double ThresholdTransitionDwellSeconds = 0.35;

		public const int MinimumPhysicalClustersForSummary = 2;

		private readonly List<MarkerSemanticCluster> _orderedClusters = new List<MarkerSemanticCluster>();

		private readonly Dictionary<PairKey, PairState> _pairStates = new Dictionary<PairKey, PairState>();

		private readonly List<PairKey> _stalePairs = new List<PairKey>();

		private readonly List<MarkerDenseAreaPresentationNode> _nodes = new List<MarkerDenseAreaPresentationNode>();

		private readonly List<PreviousDenseOwner> _previousDenseOwners = new List<PreviousDenseOwner>();

		private string _lastMembershipSignature = string.Empty;

		public IReadOnlyList<MarkerDenseAreaPresentationNode> Nodes => _nodes;

		public MarkerDenseAreaUpdate Update(IReadOnlyList<MarkerSemanticCluster> physicalClusters, double nowSeconds)
		{
			if (physicalClusters == null)
			{
				throw new ArgumentNullException("physicalClusters");
			}
			if (double.IsNaN(nowSeconds) || double.IsInfinity(nowSeconds))
			{
				nowSeconds = 0.0;
			}
			_orderedClusters.Clear();
			for (int i = 0; i < physicalClusters.Count; i++)
			{
				if (physicalClusters[i] != null)
				{
					_orderedClusters.Add(physicalClusters[i]);
				}
			}
			_orderedClusters.Sort((MarkerSemanticCluster left, MarkerSemanticCluster right) => left.StableKey.CompareTo(right.StableKey));
			ReconcileNewPairsImmediately();
			AdvanceExistingPairs(nowSeconds);
			PrunePairStates();
			List<MarkerDenseAreaPresentationNode> list = BuildPresentationNodes();
			string text = BuildMembershipSignature(list);
			bool membershipChanged = !string.Equals(text, _lastMembershipSignature, StringComparison.Ordinal);
			_lastMembershipSignature = text;
			_nodes.Clear();
			_nodes.AddRange(list);
			CapturePreviousDenseOwners();
			return new MarkerDenseAreaUpdate(_nodes, membershipChanged);
		}

		public void Clear()
		{
			_orderedClusters.Clear();
			_pairStates.Clear();
			_stalePairs.Clear();
			_nodes.Clear();
			_previousDenseOwners.Clear();
			_lastMembershipSignature = string.Empty;
		}

		private void ReconcileNewPairsImmediately()
		{
			float num = 144f;
			for (int i = 0; i < _orderedClusters.Count; i++)
			{
				for (int j = i + 1; j < _orderedClusters.Count; j++)
				{
					PairKey key = new PairKey(_orderedClusters[i].StableKey, _orderedClusters[j].StableKey);
					if (!_pairStates.ContainsKey(key))
					{
						_pairStates[key] = new PairState
						{
							Linked = (MarkerWorldPoint.DistanceSquared(_

ItemShareFix/ItemShareFix.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemShareFix.Core;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.Networking;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ItemShareFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("ItemShareFix")]
[assembly: AssemblyTitle("ItemShareFix")]
[assembly: AssemblyVersion("1.2.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 ItemShareFix
{
	internal enum C2HitchPhase
	{
		ClientSweep,
		ClientSweepPickupPresent,
		ClientRenderFrameMarkerBearing,
		NativeMarkerRender,
		EnsureCanvas,
		ResolveNativeTypography,
		GetOrCreateView,
		MeasureVisualFootprint,
		ServerBeginDistribution,
		ServerEnsureClaims,
		ServerSweepParticipantsPeriodic,
		ServerSweepParticipantsDistribution,
		ClientHudProbe,
		ClientCandidateBuild,
		ClientRendererCall,
		NativeSemanticBuild,
		NativeLayoutSolve,
		NativeApplyViews,
		NativePostRenderCleanup,
		ColdWarmupHudProbe,
		ColdWarmupNative,
		SemanticSignatureIndex,
		SemanticBuildWorldMembers,
		SemanticTrackerUpdate,
		SemanticDenseTrackerUpdate,
		SemanticClassification,
		SemanticExpansionLod,
		LayoutClusterFrameBuild,
		LayoutPlacementCandidateBuild,
		LayoutSingleMarkerPlacement,
		LayoutDirectionalAggregation,
		PresentationPlanBuild,
		ApplyTextStyle,
		ApplyGeometryLayout,
		ApplyActivation,
		LoadingNestedPrimer,
		CommandPickerDiscovery,
		CommandOptionResolution,
		CommandMarkerRegistryUpdate,
		CommandRenderInputConstruction,
		FirstMarkerActivationEndToEnd,
		Count
	}
	internal readonly struct C2HitchToken
	{
		public bool Active { get; }

		public C2HitchPhase Phase { get; }

		public long StartedTicks { get; }

		public int Frame { get; }

		public float UnscaledTime { get; }

		public int Gc0 { get; }

		public int Gc1 { get; }

		public int Gc2 { get; }

		public int MarkerCount { get; }

		public int PickupCount { get; }

		public int ParticipantCount { get; }

		public int ClaimCount { get; }

		public C2HitchToken(C2HitchPhase phase, long startedTicks, int frame, float unscaledTime, int gc0, int gc1, int gc2, int markerCount, int pickupCount, int participantCount, int claimCount)
		{
			Active = true;
			Phase = phase;
			StartedTicks = startedTicks;
			Frame = frame;
			UnscaledTime = unscaledTime;
			Gc0 = gc0;
			Gc1 = gc1;
			Gc2 = gc2;
			MarkerCount = markerCount;
			PickupCount = pickupCount;
			ParticipantCount = participantCount;
			ClaimCount = claimCount;
		}
	}
	internal static class C2HitchDiagnostics
	{
		private struct Sample
		{
			public C2HitchPhase Phase;

			public int Ordinal;

			public int Frame;

			public float UnscaledTime;

			public long ElapsedTicks;

			public bool ServerActive;

			public bool ClientActive;

			public int MarkerCountBefore;

			public int MarkerCountAfter;

			public int PickupCountBefore;

			public int PickupCountAfter;

			public int ParticipantCountBefore;

			public int ParticipantCountAfter;

			public int ClaimCountBefore;

			public int ClaimCountAfter;

			public int Gc0Delta;

			public int Gc1Delta;

			public int Gc2Delta;

			public int FirstMarkerFrame;
		}

		private const int MaxRecords = 64;

		private const float FlushDelaySeconds = 0.75f;

		private static readonly Sample[] Records = new Sample[64];

		private static readonly int[] PhaseCounts = new int[41];

		private static int _recordCount;

		private static int _flushedCount;

		private static int _firstMarkerFrame = -1;

		private static int _lastCaptureFrame = -1;

		private static float _nextFlushAt;

		private static bool _enabled;

		private static bool _captureSuppressed;

		public static void SetEnabled(bool enabled)
		{
			_enabled = enabled;
		}

		public static void SetCaptureSuppressed(bool suppressed)
		{
			_captureSuppressed = suppressed;
		}

		public static void MarkFirstMarkerFrame()
		{
			if (_enabled && !_captureSuppressed && _firstMarkerFrame < 0)
			{
				_firstMarkerFrame = Time.frameCount;
			}
		}

		public static C2HitchToken Begin(C2HitchPhase phase, int markerCount = -1, int pickupCount = -1, int participantCount = -1, int claimCount = -1)
		{
			if (!_enabled || _captureSuppressed)
			{
				return default(C2HitchToken);
			}
			if (phase < C2HitchPhase.ClientSweep || (int)phase >= PhaseCounts.Length)
			{
				return default(C2HitchToken);
			}
			if (PhaseCounts[(int)phase] >= MaxSamples(phase) || _recordCount >= 64)
			{
				return default(C2HitchToken);
			}
			return new C2HitchToken(phase, Stopwatch.GetTimestamp(), Time.frameCount, Time.unscaledTime, GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), markerCount, pickupCount, participantCount, claimCount);
		}

		public static void End(C2HitchToken token, int markerCount = -1, int pickupCount = -1, int participantCount = -1, int claimCount = -1)
		{
			if (token.Active && _recordCount < 64)
			{
				int phase = (int)token.Phase;
				if (phase >= 0 && phase < PhaseCounts.Length && PhaseCounts[phase] < MaxSamples(token.Phase))
				{
					int ordinal = ++PhaseCounts[phase];
					Records[_recordCount++] = new Sample
					{
						Phase = token.Phase,
						Ordinal = ordinal,
						Frame = token.Frame,
						UnscaledTime = token.UnscaledTime,
						ElapsedTicks = Stopwatch.GetTimestamp() - token.StartedTicks,
						ServerActive = NetworkServer.active,
						ClientActive = NetworkClient.active,
						MarkerCountBefore = token.MarkerCount,
						MarkerCountAfter = markerCount,
						PickupCountBefore = token.PickupCount,
						PickupCountAfter = pickupCount,
						ParticipantCountBefore = token.ParticipantCount,
						ParticipantCountAfter = participantCount,
						ClaimCountBefore = token.ClaimCount,
						ClaimCountAfter = claimCount,
						Gc0Delta = GC.CollectionCount(0) - token.Gc0,
						Gc1Delta = GC.CollectionCount(1) - token.Gc1,
						Gc2Delta = GC.CollectionCount(2) - token.Gc2,
						FirstMarkerFrame = _firstMarkerFrame
					};
					_lastCaptureFrame = Time.frameCount;
					_nextFlushAt = Time.unscaledTime + 0.75f;
				}
			}
		}

		public static void FlushIfReady(ManualLogSource log)
		{
			if (_enabled && _flushedCount < _recordCount && Time.frameCount > _lastCaptureFrame + 2 && !(Time.unscaledTime < _nextFlushAt))
			{
				for (int i = _flushedCount; i < _recordCount; i++)
				{
					Sample sample = Records[i];
					double num = (double)sample.ElapsedTicks * 1000000.0 / (double)Stopwatch.Frequency;
					bool flag = sample.ServerActive && sample.ClientActive;
					log.LogInfo((object)("[ItemShareFix] ISF_C2_HITCH_DIAG phase=" + PhaseToken(sample.Phase) + " method=" + MethodToken(sample.Phase) + " context=" + ContextToken(sample.Phase) + " sample=" + ((sample.Ordinal == 1) ? "first" : "subsequent") + " ordinal=" + sample.Ordinal.ToString(CultureInfo.InvariantCulture) + " frame=" + sample.Frame.ToString(CultureInfo.InvariantCulture) + " time=" + sample.UnscaledTime.ToString("F6", CultureInfo.InvariantCulture) + " elapsed_us=" + num.ToString("F3", CultureInfo.InvariantCulture) + " host=" + (flag ? "true" : "false") + " server=" + (sample.ServerActive ? "true" : "false") + " client=" + (sample.ClientActive ? "true" : "false") + " markers_before=" + sample.MarkerCountBefore.ToString(CultureInfo.InvariantCulture) + " markers_after=" + sample.MarkerCountAfter.ToString(CultureInfo.InvariantCulture) + " pickups_before=" + sample.PickupCountBefore.ToString(CultureInfo.InvariantCulture) + " pickups_after=" + sample.PickupCountAfter.ToString(CultureInfo.InvariantCulture) + " participants_before=" + sample.ParticipantCountBefore.ToString(CultureInfo.InvariantCulture) + " participants_after=" + sample.ParticipantCountAfter.ToString(CultureInfo.InvariantCulture) + " claims_before=" + sample.ClaimCountBefore.ToString(CultureInfo.InvariantCulture) + " claims_after=" + sample.ClaimCountAfter.ToString(CultureInfo.InvariantCulture) + " gc0_delta=" + sample.Gc0Delta.ToString(CultureInfo.InvariantCulture) + " gc1_delta=" + sample.Gc1Delta.ToString(CultureInfo.InvariantCulture) + " gc2_delta=" + sample.Gc2Delta.ToString(CultureInfo.InvariantCulture) + " first_marker_frame=" + sample.FirstMarkerFrame.ToString(CultureInfo.InvariantCulture) + " same_first_marker_frame=" + ((sample.FirstMarkerFrame >= 0 && sample.Frame == sample.FirstMarkerFrame) ? "true" : "false")));
				}
				_flushedCount = _recordCount;
			}
		}

		private static int MaxSamples(C2HitchPhase phase)
		{
			switch (phase)
			{
			case C2HitchPhase.EnsureCanvas:
			case C2HitchPhase.ResolveNativeTypography:
				return 1;
			case C2HitchPhase.SemanticSignatureIndex:
			case C2HitchPhase.SemanticBuildWorldMembers:
			case C2HitchPhase.SemanticTrackerUpdate:
			case C2HitchPhase.SemanticDenseTrackerUpdate:
			case C2HitchPhase.SemanticClassification:
			case C2HitchPhase.SemanticExpansionLod:
			case C2HitchPhase.LayoutClusterFrameBuild:
			case C2HitchPhase.LayoutPlacementCandidateBuild:
			case C2HitchPhase.LayoutSingleMarkerPlacement:
			case C2HitchPhase.LayoutDirectionalAggregation:
			case C2HitchPhase.PresentationPlanBuild:
			case C2HitchPhase.ApplyTextStyle:
			case C2HitchPhase.ApplyGeometryLayout:
			case C2HitchPhase.ApplyActivation:
				return 1;
			default:
				if (phase == C2HitchPhase.LoadingNestedPrimer)
				{
					return 1;
				}
				return 3;
			}
		}

		private static string PhaseToken(C2HitchPhase phase)
		{
			return phase switch
			{
				C2HitchPhase.ClientSweep => "CLIENT_SWEEP", 
				C2HitchPhase.ClientSweepPickupPresent => "CLIENT_SWEEP", 
				C2HitchPhase.ClientRenderFrameMarkerBearing => "CLIENT_RENDER_FRAME", 
				C2HitchPhase.NativeMarkerRender => "NATIVE_MARKER_RENDER", 
				C2HitchPhase.EnsureCanvas => "ENSURE_CANVAS", 
				C2HitchPhase.ResolveNativeTypography => "RESOLVE_NATIVE_TYPOGRAPHY", 
				C2HitchPhase.GetOrCreateView => "GET_OR_CREATE_VIEW", 
				C2HitchPhase.MeasureVisualFootprint => "MEASURE_VISUAL_FOOTPRINT", 
				C2HitchPhase.ServerBeginDistribution => "SERVER_BEGIN_DISTRIBUTION", 
				C2HitchPhase.ServerEnsureClaims => "SERVER_ENSURE_CLAIMS", 
				C2HitchPhase.ServerSweepParticipantsPeriodic => "SERVER_SWEEP_PARTICIPANTS", 
				C2HitchPhase.ServerSweepParticipantsDistribution => "SERVER_SWEEP_PARTICIPANTS", 
				C2HitchPhase.ClientHudProbe => "CLIENT_HUD_PROBE", 
				C2HitchPhase.ClientCandidateBuild => "CLIENT_CANDIDATE_BUILD", 
				C2HitchPhase.ClientRendererCall => "CLIENT_RENDERER_CALL", 
				C2HitchPhase.NativeSemanticBuild => "NATIVE_SEMANTIC_BUILD", 
				C2HitchPhase.NativeLayoutSolve => "NATIVE_LAYOUT_SOLVE", 
				C2HitchPhase.NativeApplyViews => "NATIVE_APPLY_VIEWS", 
				C2HitchPhase.NativePostRenderCleanup => "NATIVE_POST_RENDER_CLEANUP", 
				C2HitchPhase.ColdWarmupHudProbe => "COLD_WARMUP_HUD_PROBE", 
				C2HitchPhase.ColdWarmupNative => "COLD_WARMUP_NATIVE", 
				C2HitchPhase.SemanticSignatureIndex => "SEMANTIC_SIGNATURE_INDEX", 
				C2HitchPhase.SemanticBuildWorldMembers => "SEMANTIC_BUILD_WORLD_MEMBERS", 
				C2HitchPhase.SemanticTrackerUpdate => "SEMANTIC_TRACKER_UPDATE", 
				C2HitchPhase.SemanticDenseTrackerUpdate => "SEMANTIC_DENSE_TRACKER_UPDATE", 
				C2HitchPhase.SemanticClassification => "SEMANTIC_CLASSIFICATION", 
				C2HitchPhase.SemanticExpansionLod => "SEMANTIC_EXPANSION_LOD", 
				C2HitchPhase.LayoutClusterFrameBuild => "LAYOUT_CLUSTER_FRAME_BUILD", 
				C2HitchPhase.LayoutPlacementCandidateBuild => "LAYOUT_PLACEMENT_CANDIDATE_BUILD", 
				C2HitchPhase.LayoutSingleMarkerPlacement => "LAYOUT_SINGLE_MARKER_PLACEMENT", 
				C2HitchPhase.LayoutDirectionalAggregation => "LAYOUT_DIRECTIONAL_AGGREGATION", 
				C2HitchPhase.PresentationPlanBuild => "PRESENTATION_PLAN_BUILD", 
				C2HitchPhase.ApplyTextStyle => "APPLY_TEXT_STYLE", 
				C2HitchPhase.ApplyGeometryLayout => "APPLY_GEOMETRY_LAYOUT", 
				C2HitchPhase.ApplyActivation => "APPLY_ACTIVATION", 
				C2HitchPhase.LoadingNestedPrimer => "LOADING_NESTED_PRIMER", 
				C2HitchPhase.CommandPickerDiscovery => "COMMAND_PICKER_DISCOVERY", 
				C2HitchPhase.CommandOptionResolution => "COMMAND_OPTION_RESOLUTION", 
				C2HitchPhase.CommandMarkerRegistryUpdate => "COMMAND_MARKER_REGISTRY_UPDATE", 
				C2HitchPhase.CommandRenderInputConstruction => "COMMAND_RENDER_INPUT_CONSTRUCTION", 
				C2HitchPhase.FirstMarkerActivationEndToEnd => "FIRST_MARKER_ACTIVATION_END_TO_END", 
				_ => "UNKNOWN", 
			};
		}

		private static string MethodToken(C2HitchPhase phase)
		{
			return phase switch
			{
				C2HitchPhase.ClientSweep => "ClientPresentationCoordinator.Sweep", 
				C2HitchPhase.ClientSweepPickupPresent => "ClientPresentationCoordinator.Sweep", 
				C2HitchPhase.ClientRenderFrameMarkerBearing => "ClientPresentationCoordinator.RenderFrame", 
				C2HitchPhase.NativeMarkerRender => "NativeHudMarkerRenderer.Render", 
				C2HitchPhase.EnsureCanvas => "NativeHudMarkerRenderer.EnsureCanvas", 
				C2HitchPhase.ResolveNativeTypography => "NativeHudMarkerRenderer.ResolveNativeTypography", 
				C2HitchPhase.GetOrCreateView => "NativeHudMarkerRenderer.GetOrCreateView", 
				C2HitchPhase.MeasureVisualFootprint => "NativeHudMarkerRenderer.GetOrMeasureVisualFootprint", 
				C2HitchPhase.ServerBeginDistribution => "ServerCoordinator.BeginDistribution", 
				C2HitchPhase.ServerEnsureClaims => "ServerCoordinator.EnsureClaims", 
				C2HitchPhase.ServerSweepParticipantsPeriodic => "ServerCoordinator.SweepParticipants", 
				C2HitchPhase.ServerSweepParticipantsDistribution => "ServerCoordinator.SweepParticipants", 
				C2HitchPhase.ClientHudProbe => "ClientPresentationCoordinator.RenderFrame.HudProbe", 
				C2HitchPhase.ClientCandidateBuild => "ClientPresentationCoordinator.RenderFrame.BuildCandidates", 
				C2HitchPhase.ClientRendererCall => "ClientPresentationCoordinator.RenderFrame.RendererCall", 
				C2HitchPhase.NativeSemanticBuild => "NativeHudMarkerRenderer.Render.SemanticBuild", 
				C2HitchPhase.NativeLayoutSolve => "NativeHudMarkerRenderer.Render.LayoutSolve", 
				C2HitchPhase.NativeApplyViews => "NativeHudMarkerRenderer.Render.ApplyViews", 
				C2HitchPhase.NativePostRenderCleanup => "NativeHudMarkerRenderer.Render.PostCleanup", 
				C2HitchPhase.ColdWarmupHudProbe => "ClientPresentationCoordinator.AdvanceMarkerColdPathWarmup", 
				C2HitchPhase.ColdWarmupNative => "NativeHudMarkerRenderer.WarmColdPathStep", 
				C2HitchPhase.SemanticSignatureIndex => "NativeHudMarkerRenderer.Render.SemanticSignatureIndex", 
				C2HitchPhase.SemanticBuildWorldMembers => "NativeHudMarkerRenderer.BuildWorldMembers", 
				C2HitchPhase.SemanticTrackerUpdate => "MarkerWorldClusterTracker.Update", 
				C2HitchPhase.SemanticDenseTrackerUpdate => "MarkerDenseAreaSummaryTracker.Update", 
				C2HitchPhase.SemanticClassification => "NativeHudMarkerRenderer.ClassifyPresentationNodes", 
				C2HitchPhase.SemanticExpansionLod => "NativeHudMarkerRenderer.BuildExpansionCandidates+MarkerAdaptiveLodTracker.Update", 
				C2HitchPhase.LayoutClusterFrameBuild => "NativeHudMarkerRenderer.TryBuildCurrentClusterFrame", 
				C2HitchPhase.LayoutPlacementCandidateBuild => "NativeHudMarkerRenderer.Render.PlacementCandidateBuild", 
				C2HitchPhase.LayoutSingleMarkerPlacement => "NativeHudMarkerRenderer.ResolveCurrentPlacements.Single", 
				C2HitchPhase.LayoutDirectionalAggregation => "MarkerDirectionalAggregationPolicy.Aggregate", 
				C2HitchPhase.PresentationPlanBuild => "NativeHudMarkerRenderer.GetOrBuildPresentationPlan", 
				C2HitchPhase.ApplyTextStyle => "NativeHudMarkerRenderer.ApplyView.TextStyle", 
				C2HitchPhase.ApplyGeometryLayout => "NativeHudMarkerRenderer.ApplyView.GeometryLayout", 
				C2HitchPhase.ApplyActivation => "NativeHudMarkerRenderer.ApplyView.Activation", 
				C2HitchPhase.LoadingNestedPrimer => "NativeHudMarkerRenderer.PrimeNestedColdPathDuringInitialization", 
				C2HitchPhase.CommandPickerDiscovery => "ClientPresentationCoordinator.Sweep.CommandPickerDiscovery", 
				C2HitchPhase.CommandOptionResolution => "ClientPresentationCoordinator.Sweep.CommandOptionResolution", 
				C2HitchPhase.CommandMarkerRegistryUpdate => "ClientPresentationCoordinator.Sweep.CommandMarkerRegistryUpdate", 
				C2HitchPhase.CommandRenderInputConstruction => "ClientPresentationCoordinator.RenderFrame.CommandRenderInputConstruction", 
				C2HitchPhase.FirstMarkerActivationEndToEnd => "ClientPresentationCoordinator.FirstMarkerEligibilityToRenderComplete", 
				_ => "unknown", 
			};
		}

		private static string ContextToken(C2HitchPhase phase)
		{
			switch (phase)
			{
			default:
				switch (phase)
				{
				default:
					return "none";
				case C2HitchPhase.ColdWarmupHudProbe:
				case C2HitchPhase.ColdWarmupNative:
					return "cold-prewarm";
				case C2HitchPhase.LoadingNestedPrimer:
					return "plugin-initialization-noninteractive";
				case C2HitchPhase.CommandPickerDiscovery:
				case C2HitchPhase.CommandOptionResolution:
				case C2HitchPhase.CommandMarkerRegistryUpdate:
				case C2HitchPhase.CommandRenderInputConstruction:
				case C2HitchPhase.FirstMarkerActivationEndToEnd:
					return "first-marker-activation";
				}
			case C2HitchPhase.ClientRenderFrameMarkerBearing:
			case C2HitchPhase.NativeMarkerRender:
			case C2HitchPhase.ClientHudProbe:
			case C2HitchPhase.ClientCandidateBuild:
			case C2HitchPhase.ClientRendererCall:
			case C2HitchPhase.NativeSemanticBuild:
			case C2HitchPhase.NativeLayoutSolve:
			case C2HitchPhase.NativeApplyViews:
			case C2HitchPhase.NativePostRenderCleanup:
			case C2HitchPhase.SemanticSignatureIndex:
			case C2HitchPhase.SemanticBuildWorldMembers:
			case C2HitchPhase.SemanticTrackerUpdate:
			case C2HitchPhase.SemanticDenseTrackerUpdate:
			case C2HitchPhase.SemanticClassification:
			case C2HitchPhase.SemanticExpansionLod:
			case C2HitchPhase.LayoutClusterFrameBuild:
			case C2HitchPhase.LayoutPlacementCandidateBuild:
			case C2HitchPhase.LayoutSingleMarkerPlacement:
			case C2HitchPhase.LayoutDirectionalAggregation:
			case C2HitchPhase.PresentationPlanBuild:
			case C2HitchPhase.ApplyTextStyle:
			case C2HitchPhase.ApplyGeometryLayout:
			case C2HitchPhase.ApplyActivation:
				return "marker-bearing";
			case C2HitchPhase.ClientSweepPickupPresent:
				return "pickup-present";
			case C2HitchPhase.ServerSweepParticipantsPeriodic:
				return "periodic";
			case C2HitchPhase.ServerSweepParticipantsDistribution:
				return "distribution";
			}
		}
	}
	internal static class CommandOptionResolutionDiagnostics
	{
		private struct ActiveSample
		{
			public bool Active;

			public int Ordinal;

			public int Frame;

			public float UnscaledTime;

			public int PickerInstanceId;

			public long StartedTicks;

			public int Gc0;

			public int Gc1;

			public int Gc2;

			public long SnapshotTicks;

			public long SnapshotPreflightTicks;

			public long OptionEnumerationMemberResolutionTicks;

			public long PickupIndexSourceResolutionTicks;

			public long DedupFinalizationTicks;

			public long MetadataTicks;

			public long PickupMetadataClassificationTicks;

			public long UpstreamShareabilityTicks;

			public long PresentationFinalizationTicks;

			public int OptionsVisited;

			public int AvailableOptions;

			public int ResolvedPickupIndexes;

			public int ExactNestedAvailable;

			public int UnresolvedAvailable;

			public int DuplicatePickupCount;

			public int UpstreamShareabilityCalls;
		}

		private struct Sample
		{
			public int Ordinal;

			public int Frame;

			public float UnscaledTime;

			public int PickerInstanceId;

			public long ElapsedTicks;

			public long SnapshotTicks;

			public long SnapshotPreflightTicks;

			public long OptionEnumerationMemberResolutionTicks;

			public long PickupIndexSourceResolutionTicks;

			public long DedupFinalizationTicks;

			public long MetadataTicks;

			public long PickupMetadataClassificationTicks;

			public long UpstreamShareabilityTicks;

			public long PresentationFinalizationTicks;

			public int OptionsVisited;

			public int AvailableOptions;

			public int ResolvedPickupIndexes;

			public int ExactNestedAvailable;

			public int UnresolvedAvailable;

			public int DuplicatePickupCount;

			public int UpstreamShareabilityCalls;

			public int Gc0Delta;

			public int Gc1Delta;

			public int Gc2Delta;
		}

		private const int MaxSamples = 5;

		private const float FlushDelaySeconds = 0.75f;

		private static readonly Sample[] Records = new Sample[5];

		private static ActiveSample _active;

		private static int _recordCount;

		private static int _flushedCount;

		private static int _lastCaptureFrame = -1;

		private static float _nextFlushAt;

		private static bool _enabled;

		internal static bool CaptureActive => _active.Active;

		internal static void SetEnabled(bool enabled)
		{
			_enabled = enabled;
			if (!enabled)
			{
				_active = default(ActiveSample);
			}
		}

		internal static void Begin(int pickerInstanceId)
		{
			if (_enabled && !_active.Active && _recordCount < 5)
			{
				_active = new ActiveSample
				{
					Active = true,
					Ordinal = _recordCount + 1,
					Frame = Time.frameCount,
					UnscaledTime = Time.unscaledTime,
					PickerInstanceId = pickerInstanceId,
					StartedTicks = Stopwatch.GetTimestamp(),
					Gc0 = GC.CollectionCount(0),
					Gc1 = GC.CollectionCount(1),
					Gc2 = GC.CollectionCount(2)
				};
			}
		}

		internal static void RecordSnapshot(long totalTicks, long preflightTicks, long optionEnumerationMemberResolutionTicks, long pickupIndexSourceResolutionTicks, long dedupFinalizationTicks, int optionsVisited, int availableOptions, int resolvedPickupIndexes, int exactNestedAvailable, int unresolvedAvailable, int duplicatePickupCount)
		{
			if (_active.Active)
			{
				_active.SnapshotTicks = totalTicks;
				_active.SnapshotPreflightTicks = preflightTicks;
				_active.OptionEnumerationMemberResolutionTicks = optionEnumerationMemberResolutionTicks;
				_active.PickupIndexSourceResolutionTicks = pickupIndexSourceResolutionTicks;
				_active.DedupFinalizationTicks = dedupFinalizationTicks;
				_active.OptionsVisited = optionsVisited;
				_active.AvailableOptions = availableOptions;
				_active.ResolvedPickupIndexes = resolvedPickupIndexes;
				_active.ExactNestedAvailable = exactNestedAvailable;
				_active.UnresolvedAvailable = unresolvedAvailable;
				_active.DuplicatePickupCount = duplicatePickupCount;
			}
		}

		internal static void RecordMetadata(long totalTicks, long pickupMetadataClassificationTicks, long upstreamShareabilityTicks, long presentationFinalizationTicks, int upstreamShareabilityCalls)
		{
			if (_active.Active)
			{
				_active.MetadataTicks = totalTicks;
				_active.PickupMetadataClassificationTicks = pickupMetadataClassificationTicks;
				_active.UpstreamShareabilityTicks = upstreamShareabilityTicks;
				_active.PresentationFinalizationTicks = presentationFinalizationTicks;
				_active.UpstreamShareabilityCalls = upstreamShareabilityCalls;
			}
		}

		internal static void Complete()
		{
			if (_active.Active)
			{
				long timestamp = Stopwatch.GetTimestamp();
				ActiveSample active = _active;
				Records[_recordCount++] = new Sample
				{
					Ordinal = active.Ordinal,
					Frame = active.Frame,
					UnscaledTime = active.UnscaledTime,
					PickerInstanceId = active.PickerInstanceId,
					ElapsedTicks = timestamp - active.StartedTicks,
					SnapshotTicks = active.SnapshotTicks,
					SnapshotPreflightTicks = active.SnapshotPreflightTicks,
					OptionEnumerationMemberResolutionTicks = active.OptionEnumerationMemberResolutionTicks,
					PickupIndexSourceResolutionTicks = active.PickupIndexSourceResolutionTicks,
					DedupFinalizationTicks = active.DedupFinalizationTicks,
					MetadataTicks = active.MetadataTicks,
					PickupMetadataClassificationTicks = active.PickupMetadataClassificationTicks,
					UpstreamShareabilityTicks = active.UpstreamShareabilityTicks,
					PresentationFinalizationTicks = active.PresentationFinalizationTicks,
					OptionsVisited = active.OptionsVisited,
					AvailableOptions = active.AvailableOptions,
					ResolvedPickupIndexes = active.ResolvedPickupIndexes,
					ExactNestedAvailable = active.ExactNestedAvailable,
					UnresolvedAvailable = active.UnresolvedAvailable,
					DuplicatePickupCount = active.DuplicatePickupCount,
					UpstreamShareabilityCalls = active.UpstreamShareabilityCalls,
					Gc0Delta = GC.CollectionCount(0) - active.Gc0,
					Gc1Delta = GC.CollectionCount(1) - active.Gc1,
					Gc2Delta = GC.CollectionCount(2) - active.Gc2
				};
				_active = default(ActiveSample);
				_lastCaptureFrame = Time.frameCount;
				_nextFlushAt = Time.unscaledTime + 0.75f;
			}
		}

		internal static void FlushIfReady(ManualLogSource log)
		{
			if (_enabled && _flushedCount < _recordCount && Time.frameCount > _lastCaptureFrame + 2 && !(Time.unscaledTime < _nextFlushAt))
			{
				for (int i = _flushedCount; i < _recordCount; i++)
				{
					Sample sample = Records[i];
					log.LogInfo((object)("[ItemShareFix] ISF_COMMAND_OPTION_PROFILE sample=" + ((sample.Ordinal == 1) ? "first" : "subsequent") + " ordinal=" + sample.Ordinal.ToString(CultureInfo.InvariantCulture) + " frame=" + sample.Frame.ToString(CultureInfo.InvariantCulture) + " time=" + sample.UnscaledTime.ToString("F6", CultureInfo.InvariantCulture) + " picker_instance_id=" + sample.PickerInstanceId.ToString(CultureInfo.InvariantCulture) + " elapsed_us=" + ToMicroseconds(sample.ElapsedTicks).ToString("F3", CultureInfo.InvariantCulture) + " snapshot_us=" + ToMicroseconds(sample.SnapshotTicks).ToString("F3", CultureInfo.InvariantCulture) + " snapshot_preflight_us=" + ToMicroseconds(sample.SnapshotPreflightTicks).ToString("F3", CultureInfo.InvariantCulture) + " option_enumeration_member_resolution_us=" + ToMicroseconds(sample.OptionEnumerationMemberResolutionTicks).ToString("F3", CultureInfo.InvariantCulture) + " pickup_index_source_resolution_us=" + ToMicroseconds(sample.PickupIndexSourceResolutionTicks).ToString("F3", CultureInfo.InvariantCulture) + " dedup_finalization_us=" + ToMicroseconds(sample.DedupFinalizationTicks).ToString("F3", CultureInfo.InvariantCulture) + " metadata_us=" + ToMicroseconds(sample.MetadataTicks).ToString("F3", CultureInfo.InvariantCulture) + " pickup_metadata_catalog_classification_us=" + ToMicroseconds(sample.PickupMetadataClassificationTicks).ToString("F3", CultureInfo.InvariantCulture) + " upstream_shareability_bridge_us=" + ToMicroseconds(sample.UpstreamShareabilityTicks).ToString("F3", CultureInfo.InvariantCulture) + " presentation_finalization_us=" + ToMicroseconds(sample.PresentationFinalizationTicks).ToString("F3", CultureInfo.InvariantCulture) + " options_visited=" + sample.OptionsVisited.ToString(CultureInfo.InvariantCulture) + " available_options=" + sample.AvailableOptions.ToString(CultureInfo.InvariantCulture) + " resolved_pickup_indexes=" + sample.ResolvedPickupIndexes.ToString(CultureInfo.InvariantCulture) + " exact_nested_available=" + sample.ExactNestedAvailable.ToString(CultureInfo.InvariantCulture) + " unresolved_available=" + sample.UnresolvedAvailable.ToString(CultureInfo.InvariantCulture) + " duplicate_pickups=" + sample.DuplicatePickupCount.ToString(CultureInfo.InvariantCulture) + " upstream_shareability_calls=" + sample.UpstreamShareabilityCalls.ToString(CultureInfo.InvariantCulture) + " gc0_delta=" + sample.Gc0Delta.ToString(CultureInfo.InvariantCulture) + " gc1_delta=" + sample.Gc1Delta.ToString(CultureInfo.InvariantCulture) + " gc2_delta=" + sample.Gc2Delta.ToString(CultureInfo.InvariantCulture)));
				}
				_flushedCount = _recordCount;
			}
		}

		private static double ToMicroseconds(long ticks)
		{
			return (double)ticks * 1000000.0 / (double)Stopwatch.Frequency;
		}
	}
	internal sealed class LocalPickupPresentationGate : MonoBehaviour
	{
		private readonly Dictionary<Renderer, bool> _renderers = new Dictionary<Renderer, bool>();

		private readonly Dictionary<Light, bool> _lights = new Dictionary<Light, bool>();

		private readonly Dictionary<Behaviour, bool> _visualBehaviours = new Dictionary<Behaviour, bool>();

		private bool _hidden;

		public void ApplyHidden()
		{
			_hidden = true;
			RefreshAndApply();
		}

		public void Restore()
		{
			_hidden = false;
			KeyValuePair<Renderer, bool>[] array = _renderers.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<Renderer, bool> keyValuePair = array[i];
				if ((Object)(object)keyValuePair.Key != (Object)null)
				{
					keyValuePair.Key.forceRenderingOff = keyValuePair.Value;
				}
			}
			KeyValuePair<Light, bool>[] array2 = _lights.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<Light, bool> keyValuePair2 = array2[i];
				if ((Object)(object)keyValuePair2.Key != (Object)null)
				{
					((Behaviour)keyValuePair2.Key).enabled = keyValuePair2.Value;
				}
			}
			KeyValuePair<Behaviour, bool>[] array3 = _visualBehaviours.ToArray();
			for (int i = 0; i < array3.Length; i++)
			{
				KeyValuePair<Behaviour, bool> keyValuePair3 = array3[i];
				if ((Object)(object)keyValuePair3.Key != (Object)null)
				{
					keyValuePair3.Key.enabled = keyValuePair3.Value;
				}
			}
			_renderers.Clear();
			_lights.Clear();
			_visualBehaviours.Clear();
		}

		public void RefreshAndApply()
		{
			if (!_hidden)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					if (!_renderers.ContainsKey(val))
					{
						_renderers[val] = val.forceRenderingOff;
					}
					val.forceRenderingOff = true;
				}
			}
			Light[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Light>(true);
			foreach (Light val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					if (!_lights.ContainsKey(val2))
					{
						_lights[val2] = ((Behaviour)val2).enabled;
					}
					((Behaviour)val2).enabled = false;
				}
			}
			Behaviour[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Behaviour>(true);
			foreach (Behaviour val3 in componentsInChildren3)
			{
				if (!((Object)(object)val3 == (Object)null) && !(val3 is Light) && IsPresentationOnlyBehaviour(((object)val3).GetType().FullName ?? ((object)val3).GetType().Name))
				{
					if (!_visualBehaviours.ContainsKey(val3))
					{
						_visualBehaviours[val3] = val3.enabled;
					}
					val3.enabled = false;
				}
			}
			PruneDestroyed();
		}

		private static bool IsPresentationOnlyBehaviour(string typeName)
		{
			if (typeName.IndexOf("Highlight", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("VisualEffect", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return typeName.IndexOf("PickupDisplayGlow", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private void PruneDestroyed()
		{
			Renderer[] array = _renderers.Keys.Where((Renderer x) => (Object)(object)x == (Object)null).ToArray();
			foreach (Renderer key in array)
			{
				_renderers.Remove(key);
			}
			Light[] array2 = _lights.Keys.Where((Light x) => (Object)(object)x == (Object)null).ToArray();
			foreach (Light key2 in array2)
			{
				_lights.Remove(key2);
			}
			Behaviour[] array3 = _visualBehaviours.Keys.Where((Behaviour x) => (Object)(object)x == (Object)null).ToArray();
			foreach (Behaviour key3 in array3)
			{
				_visualBehaviours.Remove(key3);
			}
		}

		private void OnDestroy()
		{
			if (_hidden)
			{
				Restore();
			}
		}
	}
	internal sealed class LocalCommandPresentationGate : MonoBehaviour
	{
		private readonly Dictionary<Renderer, bool> _renderers = new Dictionary<Renderer, bool>();

		private readonly Dictionary<Light, bool> _lights = new Dictionary<Light, bool>();

		private readonly Dictionary<Behaviour, bool> _visualBehaviours = new Dictionary<Behaviour, bool>();

		private bool _hidden;

		public bool IsHidden => _hidden;

		public void ApplyHidden()
		{
			_hidden = true;
			RefreshAndApply();
		}

		public void Restore()
		{
			_hidden = false;
			KeyValuePair<Renderer, bool>[] array = _renderers.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<Renderer, bool> keyValuePair = array[i];
				if ((Object)(object)keyValuePair.Key != (Object)null)
				{
					keyValuePair.Key.forceRenderingOff = keyValuePair.Value;
				}
			}
			KeyValuePair<Light, bool>[] array2 = _lights.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<Light, bool> keyValuePair2 = array2[i];
				if ((Object)(object)keyValuePair2.Key != (Object)null)
				{
					((Behaviour)keyValuePair2.Key).enabled = keyValuePair2.Value;
				}
			}
			KeyValuePair<Behaviour, bool>[] array3 = _visualBehaviours.ToArray();
			for (int i = 0; i < array3.Length; i++)
			{
				KeyValuePair<Behaviour, bool> keyValuePair3 = array3[i];
				if ((Object)(object)keyValuePair3.Key != (Object)null)
				{
					keyValuePair3.Key.enabled = keyValuePair3.Value;
				}
			}
			_renderers.Clear();
			_lights.Clear();
			_visualBehaviours.Clear();
		}

		public void RefreshAndApply()
		{
			if (!_hidden)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					if (!_renderers.ContainsKey(val))
					{
						_renderers[val] = val.forceRenderingOff;
					}
					val.forceRenderingOff = true;
				}
			}
			Light[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Light>(true);
			foreach (Light val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					if (!_lights.ContainsKey(val2))
					{
						_lights[val2] = ((Behaviour)val2).enabled;
					}
					((Behaviour)val2).enabled = false;
				}
			}
			Behaviour[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Behaviour>(true);
			foreach (Behaviour val3 in componentsInChildren3)
			{
				if (!((Object)(object)val3 == (Object)null) && !(val3 is Light) && !(val3 is PickupPickerController) && !(val3 is NetworkBehaviour) && IsPresentationOnlyBehaviour(((object)val3).GetType().FullName ?? ((object)val3).GetType().Name))
				{
					if (!_visualBehaviours.ContainsKey(val3))
					{
						_visualBehaviours[val3] = val3.enabled;
					}
					val3.enabled = false;
				}
			}
			PruneDestroyed();
		}

		private static bool IsPresentationOnlyBehaviour(string typeName)
		{
			if (typeName.IndexOf("Highlight", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("VisualEffect", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return typeName.IndexOf("PickupDisplayGlow", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private void PruneDestroyed()
		{
			Renderer[] array = _renderers.Keys.Where((Renderer x) => (Object)(object)x == (Object)null).ToArray();
			foreach (Renderer key in array)
			{
				_renderers.Remove(key);
			}
			Light[] array2 = _lights.Keys.Where((Light x) => (Object)(object)x == (Object)null).ToArray();
			foreach (Light key2 in array2)
			{
				_lights.Remove(key2);
			}
			Behaviour[] array3 = _visualBehaviours.Keys.Where((Behaviour x) => (Object)(object)x == (Object)null).ToArray();
			foreach (Behaviour key3 in array3)
			{
				_visualBehaviours.Remove(key3);
			}
		}

		private void OnDestroy()
		{
			if (_hidden)
			{
				Restore();
			}
		}
	}
	internal sealed class PersonalPickupMarker
	{
		public int InstanceId { get; set; }

		public GenericPickupController Pickup { get; set; }

		public string Label { get; set; } = string.Empty;

		public string ItemSemanticKey { get; set; } = string.Empty;

		public string ClassName { get; set; } = "UNKNOWN";

		public MarkerClassKind Kind { get; set; }

		public Color TextColor { get; set; } = Color.white;

		public MarkerLifetimeKind Lifetime { get; set; }
	}
	internal sealed class PersonalCommandMarker
	{
		public int InstanceId { get; set; }

		public PickupPickerController Picker { get; set; }

		public string Label { get; set; } = string.Empty;

		public string ItemSemanticKey { get; set; } = string.Empty;

		public string ClassName { get; set; } = "UNKNOWN";

		public MarkerClassKind Kind { get; set; }

		public Color TextColor { get; set; } = Color.white;

		public MarkerLifetimeKind Lifetime { get; set; } = (MarkerLifetimeKind)3;
	}
	internal readonly struct MarkerRuntimeMetadata
	{
		public MarkerClassKind Kind { get; }

		public string ClassName { get; }

		public string Label { get; }

		public Color TextColor { get; }

		public bool ExactClass { get; }

		public MarkerRuntimeMetadata(MarkerClassKind kind, string className, string label, Color textColor, bool exactClass)
		{
			//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_0016: 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)
			Kind = kind;
			ClassName = className;
			Label = label;
			TextColor = textColor;
			ExactClass = exactClass;
		}
	}
	internal sealed class ClientPresentationCoordinator
	{
		private readonly PluginConfig _config;

		private readonly UpstreamBridge _upstream;

		private readonly ManualLogSource _log;

		private readonly Dictionary<int, LocalPickupPresentationGate> _gates = new Dictionary<int, LocalPickupPresentationGate>();

		private readonly Dictionary<int, LocalCommandPresentationGate> _commandGates = new Dictionary<int, LocalCommandPresentationGate>();

		private readonly Dictionary<int, bool> _localCommandGateDiagnosticState = new Dictionary<int, bool>();

		private readonly Dictionary<int, string> _localPickupVisualDiagnosticState = new Dictionary<int, string>();

		private readonly Dictionary<long, bool> _localPickupInteractionDiagnosticState = new Dictionary<long, bool>();

		private readonly HashSet<int> _upstreamVisibilityGateObserved = new HashSet<int>();

		private readonly List<PersonalPickupMarker> _markers = new List<PersonalPickupMarker>();

		private readonly List<PersonalCommandMarker> _commandMarkers = new List<PersonalCommandMarker>();

		private readonly List<PersonalPickupMarker> _nextOrdinaryMarkers = new List<PersonalPickupMarker>(64);

		private readonly List<PersonalCommandMarker> _nextCommandMarkers = new List<PersonalCommandMarker>(32);

		private readonly HashSet<int> _seenPickups = new HashSet<int>();

		private readonly HashSet<int> _previousOrdinaryIds = new HashSet<int>();

		private readonly HashSet<int> _seenCommandCandidateIds = new HashSet<int>();

		private readonly HashSet<int> _previousCommandIds = new HashSet<int>();

		private readonly List<int> _staleInstanceIds = new List<int>();

		private readonly List<CharacterMaster> _localMasterBuffer = new List<CharacterMaster>(4);

		private ParticipantState[] _localStateBuffer = Array.Empty<ParticipantState>();

		private bool[] _collectedBuffer = Array.Empty<bool>();

		private bool?[] _localPickedStateBuffer = Array.Empty<bool?>();

		private readonly PersonalMarkerRegistry _markerRegistry = new PersonalMarkerRegistry(96);

		private readonly HashSet<int> _ordinaryRenderLogged = new HashSet<int>();

		private readonly Dictionary<int, string> _commandRemovalReasons = new Dictionary<int, string>();

		private readonly HashSet<int> _commandOptionDisagreementLogged = new HashSet<int>();

		private readonly HashSet<int> _commandLifetimeUnknownLogged = new HashSet<int>();

		private readonly Dictionary<int, string> _commandShareabilityDiagnosticState = new Dictionary<int, string>();

		private float _nextSweep;

		private int _lastStageToken = int.MinValue;

		private int _localMastersFrame = -1;

		private CharacterMaster[] _cachedLocalMasters = Array.Empty<CharacterMaster>();

		private bool _refreshRequested;

		private int _upstreamNormalizationDepth;

		private readonly MarkerRuntimePerformanceCounters _performance = new MarkerRuntimePerformanceCounters();

		private readonly NativeHudMarkerRenderer _hudRenderer;

		private readonly Dictionary<long, MarkerHudDiagnosticState> _markerProjectionDiagnosticState = new Dictionary<long, MarkerHudDiagnosticState>();

		private readonly LocalHudPresentationProbe _localHudProbe;

		private readonly List<MarkerHudExclusionZone> _dynamicHudZones = new List<MarkerHudExclusionZone>(1);

		private readonly List<MarkerRenderInput> _renderInputs = new List<MarkerRenderInput>(96);

		private bool? _modalHudSuppressionDiagnosticState;

		private string _modalHudSuppressionReason = string.Empty;

		private bool? _messageHudDiagnosticState;

		private bool _hasMessageHudDiagnosticRect;

		private MarkerHudRect _messageHudDiagnosticRect;

		private Camera? _presentationCamera;

		private float _nextPresentationCameraRefresh;

		private float _nextPerformanceSummary;

		private int _lastPerformanceMarkerCount;

		private C2HitchToken _firstMarkerActivationTiming;

		public ClientPresentationCoordinator(PluginConfig config, UpstreamBridge upstream, ManualLogSource log)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			_config = config;
			_upstream = upstream;
			_log = log;
			C2HitchDiagnostics.SetEnabled(_config.DiagnosticInfoEnabled);
			CommandOptionResolutionDiagnostics.SetEnabled(_config.DiagnosticInfoEnabled);
			_localHudProbe = new LocalHudPresentationProbe(_performance);
			_localHudProbe.PrimeGlobalDiscoveryDuringInitialization();
			_hudRenderer = new NativeHudMarkerRenderer(log, _performance, config);
			_hudRenderer.PrimeNativeTypographyDuringInitialization();
			_hudRenderer.PrimeNestedColdPathDuringInitialization();
			_config.MarkerPresentationSettingChanged += OnMarkerPresentationSettingChanged;
			_log.LogInfo((object)"ISF_MARKER_WORLD_CLUSTER_CONFIG merge=4.50 split=6.00 dwell=0.35 solve=0.20");
		}

		private void OnMarkerPresentationSettingChanged(object? sender, EventArgs args)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			_hudRenderer.InvalidatePresentationSettings(_config.MarkerSettingsSnapshot(), _config.MarkerVisualSettingsSnapshot());
			if (sender == _config.PersonalMarkersEnabled || sender == _config.HideMarkersInTrials)
			{
				if (!_config.PersonalMarkersEnabled.Value)
				{
					_hudRenderer.Clear();
				}
				RequestRefresh();
			}
			else if (sender == _config.ShareTemporaryItems || sender == _config.ShareHallowedItems || sender == _config.ShareHexItems || sender == _config.ShareNTormatPages)
			{
				RequestRefresh();
			}
		}

		public void RecordUnityUpdate()
		{
			_performance.RecordUnityUpdate();
		}

		public void RequestRefresh()
		{
			_refreshRequested = true;
		}

		private bool MarkersSuppressedInCurrentScene()
		{
			SceneDef val = (((Object)(object)SceneInfo.instance != (Object)null) ? SceneInfo.instance.sceneDef : null);
			return MarkerSceneVisibilityPolicy.ShouldSuppress(_config.HideMarkersInTrials.Value, (val != null) ? val.baseSceneName : null, val?.nameToken);
		}

		public void OnBlockingModalLifecycleObserved(Component component)
		{
			_localHudProbe.ObserveBlockingModalLifecycle(component);
		}

		public void OnHudLifecycleObserved(Component component)
		{
			_localHudProbe.ObserveHudLifecycle(component);
		}

		public void OnTmpSubMeshOnDisable(TMP_SubMeshUI subMesh)
		{
			_hudRenderer.ObserveTmpSubMeshOnDisable(subMesh);
		}

		public bool TryEvaluateLocalCollected(GenericPickupController pickup, out bool collectedByAllLocalParticipants)
		{
			collectedByAllLocalParticipants = false;
			if (!_config.Enabled.Value || !_config.PersonalPickupVisibilityRepairEnabled.Value || !_upstream.IsIndividualMode || !_upstream.HideCollectedOrbsEnabled || (Object)(object)pickup == (Object)null || KnownProgressionPickupCompatibility.IsExcluded(pickup) || !_upstream.IsShareable(pickup))
			{
				return false;
			}
			CharacterMaster[] localMastersSnapshot = GetLocalMastersSnapshot();
			if (localMastersSnapshot.Length == 0)
			{
				return false;
			}
			collectedByAllLocalParticipants = localMastersSnapshot.All((CharacterMaster master) => _upstream.HasCollected(pickup, master));
			return true;
		}

		public bool ShouldSuppressLocalPickupInteraction(GenericPickupController pickup, Interactor interactor)
		{
			if (!_config.Enabled.Value || !_config.PersonalPickupVisibilityRepairEnabled.Value || !_upstream.IsIndividualMode || !_upstream.HideCollectedOrbsEnabled || (Object)(object)pickup == (Object)null || (Object)(object)interactor == (Object)null || KnownProgressionPickupCompatibility.IsExcluded(pickup))
			{
				return false;
			}
			bool flag = _upstream.IsShareable(pickup);
			CharacterBody component = ((Component)interactor).GetComponent<CharacterBody>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.master == (Object)null)
			{
				return false;
			}
			CharacterMaster master = component.master;
			bool hasAuthority = ((NetworkBehaviour)master).hasAuthority;
			bool flag2 = hasAuthority && _upstream.HasCollected(pickup, master);
			bool flag3 = LocalPickupSuppressionPolicy.ShouldSuppressInteractor(true, true, flag, hasAuthority, flag2);
			if (hasAuthority)
			{
				LogLocalInteractionGateTransition(pickup, master, flag2, flag3);
			}
			return flag3;
		}

		public void OnUpstreamVisibilityApplied(GenericPickupController pickup)
		{
			if ((Object)(object)pickup == (Object)null || _upstreamNormalizationDepth > 0)
			{
				return;
			}
			int instanceID = ((Object)pickup).GetInstanceID();
			if (!TryEvaluateLocalCollected(pickup, out var collectedByAllLocalParticipants))
			{
				ReleaseGate(instanceID);
				RequestRefresh();
				return;
			}
			if (!collectedByAllLocalParticipants)
			{
				ReleaseGate(instanceID);
				return;
			}
			NormalizeUpstreamForGate(pickup);
			if (!_gates.TryGetValue(instanceID, out LocalPickupPresentationGate value) || (Object)(object)value == (Object)null)
			{
				value = ((Component)pickup).gameObject.GetComponent<LocalPickupPresentationGate>() ?? ((Component)pickup).gameObject.AddComponent<LocalPickupPresentationGate>();
				_gates[instanceID] = value;
			}
			value.ApplyHidden();
			if (_config.DiagnosticInfoEnabled && _upstreamVisibilityGateObserved.Add(instanceID))
			{
				LogInfo("ISF_C20_LOCAL_PICKUP_GATE pickup=" + instanceID.ToString(CultureInfo.InvariantCulture) + " localMaster=process localCollected=all visualSuppressed=true interactionSuppressed=participant-specific action=upstream-visibility-applied reason=all-local-collected");
			}
		}

		public void Tick()
		{
			int num = CurrentStageToken();
			if (num != _lastStageToken)
			{
				RestoreAll("stage-or-run-boundary");
				_localHudProbe.InvalidateLifecycle();
				_presentationCamera = null;
				_nextPresentationCameraRefresh = 0f;
				_lastStageToken = num;
				_refreshRequested = true;
			}
			if (_refreshRequested || !(Time.unscaledTime < _nextSweep))
			{
				_refreshRequested = false;
				_nextSweep = Time.unscaledTime + Math.Max(0.08f, _config.PresentationSweepSeconds.Value);
				Sweep();
			}
		}

		public void RenderFrame()
		{
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: 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_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			_performance.RecordRenderFrame();
			C2HitchDiagnostics.SetEnabled(_config.DiagnosticInfoEnabled);
			CommandOptionResolutionDiagnostics.SetEnabled(_config.DiagnosticInfoEnabled);
			C2HitchDiagnostics.FlushIfReady(_log);
			CommandOptionResolutionDiagnostics.FlushIfReady(_log);
			bool flag = _config.Enabled.Value && _config.PersonalMarkersEnabled.Value && !MarkersSuppressedInCurrentScene() && (_markers.Count > 0 || _commandMarkers.Count > 0);
			if (!flag)
			{
				if (_lastPerformanceMarkerCount > 0)
				{
					EmitPerformanceSummary("marker-teardown", 0, force: true);
				}
				_lastPerformanceMarkerCount = 0;
				_hudRenderer.SetPresentationSuppressed(suppressed: false);
				_hudRenderer.Clear();
				if (_config.Enabled.Value && _config.PersonalMarkersEnabled.Value && !MarkersSuppressedInCurrentScene())
				{
					AdvanceMarkerColdPathWarmup(allowRefresh: true);
				}
			}
			else
			{
				if (!AdvanceMarkerColdPathWarmup(allowRefresh: false))
				{
					return;
				}
				int num = _markers.Count + _commandMarkers.Count;
				C2HitchDiagnostics.MarkFirstMarkerFrame();
				C2HitchToken token = C2HitchDiagnostics.Begin(C2HitchPhase.ClientRenderFrameMarkerBearing, num);
				try
				{
					_lastPerformanceMarkerCount = num;
					MaybeEmitPerformanceSummary(num);
					C2HitchToken token2 = C2HitchDiagnostics.Begin(C2HitchPhase.ClientHudProbe, num);
					try
					{
						string reason;
						bool flag2 = _localHudProbe.TryGetBlockingModalCached(out reason);
						if (!_modalHudSuppressionDiagnosticState.HasValue || _modalHudSuppressionDiagnosticState.Value != flag2 || (flag2 && !string.Equals(_modalHudSuppressionReason, reason, StringComparison.Ordinal)))
						{
							_modalHudSuppressionDiagnosticState = flag2;
							_modalHudSuppressionReason = reason;
							LogInfo("ISF_MARKER_HUD_SUPPRESS reason=" + (flag2 ? reason : "pause-menu") + " active=" + flag2);
						}
						_hudRenderer.SetPresentationSuppressed(flag2);
						if (!MarkerPresentationPolicy.ShouldRenderHudMarkers(flag, flag2))
						{
							return;
						}
						_dynamicHudZones.Clear();
						MarkerHudRect rect;
						bool flag3 = _localHudProbe.TryGetVisibleMessageHudRectCached(out rect);
						if (flag3)
						{
							_dynamicHudZones.Add(new MarkerHudExclusionZone("message-hud-runtime", ((MarkerHudRect)(ref rect)).Left, ((MarkerHudRect)(ref rect)).Right, ((MarkerHudRect)(ref rect)).Bottom, ((MarkerHudRect)(ref rect)).Top));
						}
						bool flag4 = flag3 && (!_hasMessageHudDiagnosticRect || !SameDiagnosticRect(_messageHudDiagnosticRect, rect));
						if (!_messageHudDiagnosticState.HasValue || _messageHudDiagnosticState.Value != flag3 || flag4)
						{
							_messageHudDiagnosticState = flag3;
							_hasMessageHudDiagnosticRect = flag3;
							_messageHudDiagnosticRect = rect;
							LogInfo("ISF_MARKER_MESSAGE_HUD active=" + flag3 + (flag3 ? (" rect=" + FormatMarkerRect(rect)) : string.Empty));
						}
					}
					finally
					{
						C2HitchDiagnostics.End(token2, num);
					}
					Camera val = null;
					MarkerLanguage val2 = (MarkerLanguage)0;
					C2HitchToken token3 = C2HitchDiagnostics.Begin(C2HitchPhase.ClientCandidateBuild, num);
					try
					{
						val = GetPresentationCamera();
						if ((Object)(object)val == (Object)null || !TryGetFiniteCameraPosition(val, out var cameraPosition))
						{
							_hudRenderer.Clear();
							return;
						}
						val2 = CurrentMarkerLanguage();
						_renderInputs.Clear();
						int num2 = 0;
						while (num2 < _markers.Count)
						{
							PersonalPickupMarker personalPickupMarker = _markers[num2];
							if (!TryResolveOrdinaryMarkerTarget(personalPickupMarker.Pickup, out Vector3 worldPosition, out string invalidReason))
							{
								RemoveOrdinaryMarkerNow(personalPickupMarker, invalidReason);
								continue;
							}
							if (!TryResolvePresentationDistance(cameraPosition, worldPosition, out int roundedDistanceMeters, out invalidReason))
							{
								RemoveOrdinaryMarkerNow(personalPickupMarker, invalidReason);
								continue;
							}
							_renderInputs.Add(new MarkerRenderInput(new PersonalMarkerIdentity((PersonalMarkerKind)0, personalPickupMarker.InstanceId), worldPosition + Vector3.up * 1.2f, roundedDistanceMeters, PickupLabel(personalPickupMarker.Pickup, val2), personalPickupMarker.ItemSemanticKey, personalPickupMarker.ClassName, personalPickupMarker.Kind, personalPickupMarker.TextColor, ResolvePickupIcon(personalPickupMarker.Pickup), personalPickupMarker.Lifetime));
							num2++;
						}
						C2HitchToken token4 = C2HitchDiagnostics.Begin(C2HitchPhase.CommandRenderInputConstruction, _commandMarkers.Count);
						try
						{
							int num3 = 0;
							while (num3 < _commandMarkers.Count)
							{
								PersonalCommandMarker personalCommandMarker = _commandMarkers[num3];
								if (!TryResolveCommandMarkerTarget(personalCommandMarker.Picker, out Vector3 worldPosition2, out string invalidReason2))
								{
									RemoveCommandMarkerNow(personalCommandMarker, invalidReason2);
									continue;
								}
								if (!TryResolvePresentationDistance(cameraPosition, worldPosition2, out int roundedDistanceMeters2, out invalidReason2))
								{
									RemoveCommandMarkerNow(personalCommandMarker, invalidReason2);
									continue;
								}
								_renderInputs.Add(new MarkerRenderInput(new PersonalMarkerIdentity((PersonalMarkerKind)1, personalCommandMarker.InstanceId), worldPosition2 + Vector3.up * 1.35f, roundedDistanceMeters2, MarkerClassPolicy.LocalizedReadableClassLabel(personalCommandMarker.Kind, val2), personalCommandMarker.ItemSemanticKey, personalCommandMarker.ClassName, personalCommandMarker.Kind, personalCommandMarker.TextColor, null, personalCommandMarker.Lifetime));
								num3++;
							}
						}
						finally
						{
							C2HitchDiagnostics.End(token4, _renderInputs.Count);
						}
					}
					finally
					{
						C2HitchDiagnostics.End(token3, _renderInputs.Count);
					}
					if ((Object)(object)val == (Object)null)
					{
						return;
					}
					C2HitchToken token5 = C2HitchDiagnostics.Begin(C2HitchPhase.ClientRendererCall, _renderInputs.Count);
					try
					{
						_hudRenderer.Render(val, _renderInputs, _config.MarkerSettingsSnapshot(), _config.MarkerVisualSettingsSnapshot(), val2, OnMarkerRendered, _dynamicHudZones);
					}
					finally
					{
						C2HitchDiagnostics.End(token5, _renderInputs.Count);
						if (_firstMarkerActivationTiming.Active)
						{
							C2HitchDiagnostics.End(_firstMarkerActivationTiming, _markers.Count + _commandMarkers.Count);
							_firstMarkerActivationTiming = default(C2HitchToken);
						}
					}
				}
				finally
				{
					C2HitchDiagnostics.End(token, _markers.Count + _commandMarkers.Count);
				}
			}
		}

		private bool AdvanceMarkerColdPathWarmup(bool allowRefresh)
		{
			if ((Object)(object)Run.instance == (Object)null || (Object)(object)GetPresentationCamera() == (Object)null)
			{
				return false;
			}
			C2HitchToken token = C2HitchDiagnostics.Begin(C2HitchPhase.ColdWarmupHudProbe, _markers.Count + _commandMarkers.Count);
			bool flag;
			try
			{
				flag = _localHudProbe.WarmColdPathStep(allowRefresh);
			}
			finally
			{
				C2HitchDiagnostics.End(token, _markers.Count + _commandMarkers.Count);
			}
			if (!flag)
			{
				return false;
			}
			C2HitchToken token2 = C2HitchDiagnostics.Begin(C2HitchPhase.ColdWarmupNative, _markers.Count + _commandMarkers.Count);
			try
			{
				return _hudRenderer.WarmColdPathStep();
			}
			finally
			{
				C2HitchDiagnostics.End(token2, _markers.Count + _commandMarkers.Count);
			}
		}

		public void Dispose()
		{
			_config.MarkerPresentationSettingChanged -= OnMarkerPresentationSettingChanged;
			RestoreAll("external-or-plugin-teardown");
			_hudRenderer.Dispose();
		}

		public void RestoreAll()
		{
			RestoreAll("external-or-plugin-teardown");
		}

		private void RestoreAll(string reason)
		{
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			if (_markers.Count > 0 || _commandMarkers.Count > 0)
			{
				EmitPerformanceSummary(reason, 0, force: true);
			}
			_lastPerformanceMarkerCount = 0;
			LocalPickupPresentationGate[] array = _gates.Values.ToArray();
			foreach (LocalPickupPresentationGate localPickupPresentationGate in array)
			{
				if (!((Object)(object)localPickupPresentationGate == (Object)null))
				{
					localPickupPresentationGate.Restore();
					Object.Destroy((Object)(object)localPickupPresentationGate);
				}
			}
			_gates.Clear();
			LocalCommandPresentationGate[] array2 = _commandGates.Values.ToArray();
			foreach (LocalCommandPresentationGate localCommandPresentationGate in array2)
			{
				if (!((Object)(object)localCommandPresentationGate == (Object)null))
				{
					localCommandPresentationGate.Restore();
					Object.Destroy((Object)(object)localCommandPresentationGate);
				}
			}
			_commandGates.Clear();
			_localCommandGateDiagnosticState.Clear();
			_localPickupVisualDiagnosticState.Clear();
			_localPickupInteractionDiagnosticState.Clear();
			_upstreamVisibilityGateObserved.Clear();
			PersonalCommandMarker[] array3 = _commandMarkers.ToArray();
			foreach (PersonalCommandMarker personalCommandMarker in array3)
			{
				LogCommandCleanup(personalCommandMarker.InstanceId, reason);
			}
			_markers.Clear();
			_commandMarkers.Clear();
			_markerRegistry.Clear();
			_ordinaryRenderLogged.Clear();
			_commandRemovalReasons.Clear();
			_commandOptionDisagreementLogged.Clear();
			_commandShareabilityDiagnosticState.Clear();
			_markerProjectionDiagnosticState.Clear();
			_modalHudSuppressionDiagnosticState = null;
			_modalHudSuppressionReason = string.Empty;
			_messageHudDiagnosticState = null;
			_hasMessageHudDiagnosticRect = false;
			_messageHudDiagnosticRect = default(MarkerHudRect);
			_localHudProbe.InvalidateLifecycle();
			_presentationCamera = null;
			_nextPresentationCameraRefresh = 0f;
			_hudRenderer.SetPresentationSuppressed(suppressed: false);
			_hudRenderer.Clear();
		}

		private unsafe void Sweep()
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected I4, but got Unknown
			//IL_011a: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Invalid comparison between Unknown and I4
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0710: Unknown result type (might be due to invalid IL or missing references)
			//IL_0712: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0811: Unknown result type (might be due to invalid IL or missing references)
			//IL_0816: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eb0: Unknown result type (might be due to invalid IL or missing references)
			//IL_085a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0868: Unknown result type (might be due to invalid IL or missing references)
			//IL_086b: Invalid comparison between Unknown and I4
			//IL_0ed7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0edc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ebf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ec4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0910: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b10: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b15: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b31: Invalid comparison between Unknown and I4
			//IL_0b3c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b3f: Invalid comparison between Unknown and I4
			//IL_0a2a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bb9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bcb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bce: Invalid comparison between Unknown and I4
			//IL_0c6c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd3: Invalid comparison between Unknown and I4
			if (!_config.Enabled.Value || !_upstream.IsIndividualMode)
			{
				RestoreAll("feature-disabled-or-non-individual-mode");
				return;
			}
			CharacterMaster[] localMastersSnapshot = GetLocalMastersSnapshot();
			if (localMastersSnapshot.Length == 0)
			{
				RestoreAll("no-local-master");
				return;
			}
			C2HitchDiagnostics.SetEnabled(_config.DiagnosticInfoEnabled);
			CommandOptionResolutionDiagnostics.SetEnabled(_config.DiagnosticInfoEnabled);
			bool flag = _config.PersonalMarkersEnabled.Value && !MarkersSuppressedInCurrentScene();
			List<GenericPickupController> instancesList = InstanceTracker.GetInstancesList<GenericPickupController>();
			C2HitchToken token = C2HitchDiagnostics.Begin(C2HitchPhase.ClientSweep, _markers.Count + _commandMarkers.Count, instancesList.Count);
			C2HitchToken token2 = ((instancesList.Count > 0) ? C2HitchDiagnostics.Begin(C2HitchPhase.ClientSweepPickupPresent, _markers.Count + _commandMarkers.Count, instancesList.Count) : default(C2HitchToken));
			try
			{
				EnsureParticipantBuffers(localMastersSnapshot.Length);
				ParticipantState[] localStateBuffer = _localStateBuffer;
				for (int i = 0; i < localMastersSnapshot.Length; i++)
				{
					localStateBuffer[i] = (ParticipantState)(int)LocalParticipantResolver.ClassifyLocal(localMastersSnapshot[i]);
				}
				MarkerLanguage val = CurrentMarkerLanguage();
				Camera presentationCamera = GetPresentationCamera();
				Vector3 cameraPosition = default(Vector3);
				bool flag2 = (Object)(object)presentationCamera != (Object)null && TryGetFiniteCameraPosition(presentationCamera, out cameraPosition);
				_markerRegistry.BeginSweep();
				_nextOrdinaryMarkers.Clear();
				_seenPickups.Clear();
				_previousOrdinaryIds.Clear();
				for (int j = 0; j < _markers.Count; j++)
				{
					_previousOrdinaryIds.Add(_markers[j].InstanceId);
				}
				int num = 0;
				int roundedDistanceMeters;
				foreach (GenericPickupController item in instancesList)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					int instanceID = ((Object)item).GetInstanceID();
					Vector3 worldPosition;
					string invalidReason;
					if (KnownProgressionPickupCompatibility.IsExcluded(item))
					{
						ReleaseGate(instanceID);
						_markerRegistry.Remove((PersonalMarkerKind)0, instanceID);
						_ordinaryRenderLogged.Remove(instanceID);
					}
					else if (!TryResolveOrdinaryMarkerTarget(item, out worldPosition, out invalidReason) || (flag2 && !TryResolvePresentationDistance(cameraPosition, worldPosition, out roundedDistanceMeters, out invalidReason)))
					{
						ReleaseGate(instanceID);
						_markerRegistry.Remove((PersonalMarkerKind)0, instanceID);
						_ordinaryRenderLogged.Remove(instanceID);
						if (_previousOrdinaryIds.Contains(instanceID))
						{
							LogOrdinaryCleanup(instanceID, invalidReason);
						}
					}
					else
					{
						if (!_upstream.IsShareable(item))
						{
							continue;
						}
						_seenPickups.Add(instanceID);
						bool[] collectedBuffer = _collectedBuffer;
						int num2 = 0;
						for (int k = 0; k < localMastersSnapshot.Length; k++)
						{
							if (collectedBuffer[k] = _upstream.HasCollected(item, localMastersSnapshot[k]))
							{
								num2++;
							}
						}
						bool flag3 = LocalPickupSuppressionPolicy.ShouldSuppressProcessVisual(_config.PersonalPickupVisibilityRepairEnabled.Value, _upstream.HideCollectedOrbsEnabled, collectedBuffer.Length, num2);
						if (flag3)
						{
							if (!_gates.TryGetValue(instanceID, out LocalPickupPresentationGate value) || (Object)(object)value == (Object)null)
							{
								NormalizeUpstreamForGate(item);
								value = ((Component)item).gameObject.GetComponent<LocalPickupPresentationGate>() ?? ((Component)item).gameObject.AddComponent<LocalPickupPresentationGate>();
								_gates[instanceID] = value;
							}
							value.ApplyHidden();
						}
						else
						{
							ReleaseGate(instanceID);
						}
						LogLocalVisualGateTransition(item, num2, collectedBuffer.Length, flag3);
						UniquePickup pickup = item.pickup;
						MarkerLifetimeKind val2 = MarkerLifetimePolicy.FromTemporaryFlag(((UniquePickup)(ref pickup)).isTempItem);
						if (flag && MarkerLifetimePolicy.IsMarkerEligible(val2, _config.ShareTemporaryItems.Value) && num < 64 && ShouldShowMarker(localStateBuffer, collectedBuffer))
						{
							string text = MarkerPresentationPolicy.NormalizeLabel(PickupLabel(item, val), MarkerTextLocalization.FallbackSharedPickup(val));
							MarkerRuntimeMetadata markerRuntimeMetadata = ResolvePickupMarkerMetadata(item.pickup.pickupIndex);
							if ((int)_markerRegistry.MarkPending((PersonalMarkerKind)0, instanceID, text) != 3)
							{
								_nextOrdinaryMarkers.Add(new PersonalPickupMarker
								{
									InstanceId = instanceID,
									Pickup = item,
									Label = text,
									ItemSemanticKey = PickupSemanticKey(item),
									ClassName = markerRuntimeMetadata.ClassName,
									Kind = markerRuntimeMetadata.Kind,
									TextColor = markerRuntimeMetadata.TextColor,
									Lifetime = val2
								});
								num++;
							}
						}
					}
				}
				_staleInstanceIds.Clear();
				foreach (int key in _gates.Keys)
				{
					if (!_seenPickups.Contains(key))
					{
						_staleInstanceIds.Add(key);
					}
				}
				for (int l = 0; l < _staleInstanceIds.Count; l++)
				{
					ReleaseGate(_staleInstanceIds[l]);
				}
				_nextCommandMarkers.Clear();
				_seenCommandCandidateIds.Clear();
				_commandRemovalReasons.Clear();
				_previousCommandIds.Clear();
				for (int m = 0; m < _commandMarkers.Count; m++)
				{
					_previousCommandIds.Add(_commandMarkers[m].InstanceId);
				}
				int num3 = 0;
				if (_upstream.ShareCommandPicksEnabled)
				{
					C2HitchToken token3 = C2HitchDiagnostics.Begin(C2HitchPhase.CommandPickerDiscovery, _markers.Count + _commandMarkers.Count);
					List<PickupPickerController> instancesList2 = InstanceTracker.GetInstancesList<PickupPickerController>();
					C2HitchDiagnostics.End(token3, _markers.Count + _commandMarkers.Count, instancesList2.Count);
					foreach (PickupPickerController item2 in instancesList2)
					{
						if ((Object)(object)item2 == (Object)null)
						{
							continue;
						}
						int instanceID2 = ((Object)item2).GetInstanceID();
						if (!_upstream.IsCommandCube(item2))
						{
							ReleaseCommandGate(instanceID2, "classifier-false");
							if (_previousCommandIds.Contains(instanceID2))
							{
								_commandRemovalReasons[instanceID2] = "classifier-false";
							}
							continue;
						}
						_seenCommandCandidateIds.Add(instanceID2);
						bool?[] localPickedStateBuffer = _localPickedStateBuffer;
						bool flag4 = false;
						bool flag5 = true;
						for (int n = 0; n < localMastersSnapshot.Length; n++)
						{
							if (!_upstream.TryHasCommandPicked(item2, localMastersSnapshot[n], out var picked))
							{
								localPickedStateBuffer[n] = null;
								flag5 = false;
								continue;
							}
							localPickedStateBuffer[n] = picked;
							if (ProjectionPolicy.ShowPersonalMarker(true, localStateBuffer[n], picked, false))
							{
								flag4 = true;
							}
						}
						LocalCommandPresentationDecision decision = LocalCommandPresentationPolicy.Evaluate((IReadOnlyList<bool?>)localPickedStateBuffer);
						ApplyLocalCommandPresentation(item2, decision);
						if (!flag)
						{
							if (_previousCommandIds.Contains(instanceID2))
							{
								_commandRemovalReasons[instanceID2] = "markers-disabled";
							}
							continue;
						}
						if (!TryResolveCommandMarkerTarget(item2, out Vector3 worldPosition2, out string invalidReason2) || (flag2 && !TryResolvePresentationDistance(cameraPosition, worldPosition2, out roundedDistanceMeters, out invalidReason2)))
						{
							_markerRegistry.Remove((PersonalMarkerKind)1, instanceID2);
							if (_previousCommandIds.Contains(instanceID2))
							{
								LogCommandCleanup(instanceID2, invalidReason2);
							}
							continue;
						}
						bool flag6 = flag4 || flag5;
						if (num3 >= 32 || !MarkerPresentationPolicy.ShouldTrackCommandMarker(flag, _upstream.IsIndividualMode, _upstream.ShareCommandPicksEnabled, true, flag6, flag4))
						{
							if (_previousCommandIds.Contains(instanceID2))
							{
								_commandRemovalReasons[instanceID2] = (flag5 ? "local-completed" : "local-state-unresolved");
							}
							continue;
						}
						C2HitchToken token4 = C2HitchDiagnostics.Begin(C2HitchPhase.CommandOptionResolution, _markers.Count + _commandMarkers.Count);
						CommandOptionResolutionDiagnostics.Begin(instanceID2);
						MarkerLifetimeKind val3 = (MarkerLifetimeKind)3;
						int num4 = 0;
						int num5 = 0;
						MarkerRuntimeMetadata markerRuntimeMetadata2;
						string optionSource;
						int resolvedOptionCount;
						bool sourceDisagreement;
						CommandShareabilityDecision shareability;
						try
						{
							_upstream.TryBuildCommandChoiceSnapshot(item2, out UpstreamBridge.CommandChoiceSnapshot snapshot);
							markerRuntimeMetadata2 = ResolveCommandMarkerMetadata(snapshot, val, out optionSource, out resolvedOptionCount, out sourceDisagreement, out shareability, item2);
							val3 = snapshot.Lifetime;
							num4 = snapshot.ExactNestedAvailableOptionCount;
							num5 = snapshot.UnresolvedAvailableOptionCount;
						}
						finally
						{
							CommandOptionResolutionDiagnostics.Complete();
							C2HitchDiagnostics.End(token4, _markers.Count + _commandMarkers.Count);
						}
						string text2 = MarkerPresentationPolicy.NormalizeLabel(markerRuntimeMetadata2.Label, MarkerTextLocalization.FallbackCommandChoice(val));
						if ((int)val3 == 3 && _commandLifetimeUnknownLogged.Add(instanceID2))
						{
							LogInfo("ISF_COMMAND_LIFETIME pickerInstanceId=" + instanceID2.ToString(CultureInfo.InvariantCulture) + " lifetime=Unknown exactNestedAvailable=" + num4.ToString(CultureInfo.InvariantCulture) + " unresolvedAvailable=" + num5.ToString(CultureInfo.InvariantCulture) + " assertion=none");
						}
						if (sourceDisagreement && _commandOptionDisagreementLogged.Add(instanceID2))
						{
							LogInfo("ISF_COMMAND_OPTION_SOURCE_DISAGREEMENT pickerInstanceId=" + instanceID2.ToString(CultureInfo.InvariantCulture) + " nestedWins=True optionSource=" + optionSource);
						}
						if (!MarkerLifetimePolicy.IsMarkerEligible(val3, _config.ShareTemporaryItems.Value))
						{
							_commandShareabilityDiagnosticState[instanceID2] = "temporary-sharing-disabled";
							if (_previousCommandIds.Contains(instanceID2))
							{
								_commandRemovalReasons[instanceID2] = "temporary-sharing-disabled";
							}
							continue;
						}
						if (!((CommandShareabilityDecision)(ref shareability)).MarkerEligible)
						{
							string text3 = ((CommandShareabilityDecision)(ref shareability)).DiagnosticToken + ":" + ((CommandShareabilityDecision)(ref shareability)).FilterReason;
							if (!_commandShareabilityDiagnosticState.TryGetValue(instanceID2, out string value2) || !string.Equals(value2, text3, StringComparison.Ordinal))
							{
								_commandShareabilityDiagnosticState[instanceID2] = text3;
								LogInfo("ISF_COMMAND_MARKER filtered pickerInstanceId=" + instanceID2.ToString(CultureInfo.InvariantCulture) + " optionSource=" + optionSource + " resolvedOptionCount=" + resolvedOptionCount.ToString(CultureInfo.InvariantCulture) + " class=" + markerRuntimeMetadata2.ClassName + " label=" + text2 + " color=" + ColorEvidence(markerRuntimeMetadata2.TextColor) + " shareability=" + ((CommandShareabilityDecision)(ref shareability)).DiagnosticToken + " reason=" + ((CommandShareabilityDecision)(ref shareability)).FilterReason);
							}
							if (_previousCommandIds.Contains(instanceID2))
							{
								_commandRemovalReasons[instanceID2] = ((CommandShareabilityDecision)(ref shareability)).FilterReason;
							}
							continue;
						}
						_commandShareabilityDiagnosticState[instanceID2] = ((CommandShareabilityDecision)(ref shareability)).DiagnosticToken + ":eligible";
						if (!_firstMarkerActivationTiming.Active)
						{
							_firstMarkerActivationTiming = C2HitchDiagnostics.Begin(C2HitchPhase.FirstMarkerActivationEndToEnd, _markers.Count + _commandMarkers.Count);
						}
						C2HitchToken token5 = C2HitchDiagnostics.Begin(C2HitchPhase.CommandMarkerRegistryUpdate, _markers.Count + _commandMarkers.Count);
						PersonalMarkerTransition val4 = _markerRegistry.MarkPending((PersonalMarkerKind)1, instanceID2, text2);
						C2HitchDiagnostics.End(token5, _markers.Count + _commandMarkers.Count + (((int)val4 == 1) ? 1 : 0));
						if ((int)val4 == 3)
						{
							_firstMarkerActivationTiming = default(C2HitchToken);
							continue;
						}
						_nextCommandMarkers.Add(new PersonalCommandMarker
						{
							InstanceId = instanceID2,
							Picker = item2,
							Label = text2,
							ItemSemanticKey = "COMMAND:" + instanceID2.ToString(CultureInfo.InvariantCulture),
							ClassName = markerRuntimeMetadata2.ClassName,
							Kind = markerRuntimeMetadata2.Kind,
							TextColor = markerRuntimeMetadata2.TextColor,
							Lifetime = val3
						});
						num3++;
						if ((int)val4 == 1 || (int)val4 == 2)
						{
							string[] obj = new string[28]
							{
								"ISF_COMMAND_MARKER pending pickerInstanceId=",
								instanceID2.ToString(CultureInfo.InvariantCulture),
								" localPending=True providerHasState=",
								_upstream.HasPickerProviderState(item2).ToString(),
								" discovery=InstanceTracker optionSource=",
								optionSource,
								" resolvedOptionCount=",
								resolvedOptionCount.ToString(CultureInfo.InvariantCulture),
								" class=",
								markerRuntimeMetadata2.ClassName,
								" label=",
								text2,
								" color=",
								ColorEvidence(markerRuntimeMetadata2.TextColor),
								" style=",
								MarkerPresentationPolicy.NativeHudStyleToken,
								" renderer=canvas-tmp-ui-graphic fontSize=",
								null,
								null,
								null,
								null,
								null,
								null,
								null,
								null,
								null,
								null,
								null
							};
							roundedDistanceMeters = MarkerPresentationPolicy.BuildNativeHudFontSize(Screen.height);
							obj[17] = roundedDistanceMeters.ToString(CultureInfo.InvariantCulture);
							obj[18] = " shareability=";
							obj[19] = ((CommandShareabilityDecision)(ref shareability)).DiagnosticToken;
							obj[20] = " exactClass=";
							obj[21] = markerRuntimeMetadata2.ExactClass.ToString();
							obj[22] = " lifetime=";
							obj[23] = ((object)(*(MarkerLifetimeKind*)(&val3))/*cast due to .constrained prefix*/).ToString();
							obj[24] = " lifetimeExactNested=";
							obj[25] = num4.ToString(CultureInfo.InvariantCulture);
							obj[26] = " lifetimeUnresolved=";
							obj[27] = num5.ToString(CultureInfo.InvariantCulture);
							LogInfo(string.Concat(obj));
						}
					}
				}
				_staleInstanceIds.Clear();
				foreach (int key2 in _commandGates.Keys)
				{
					if (!_seenCommandCandidateIds.Contains(key2))
					{
						_staleInstanceIds.Add(key2);
					}
				}
				for (int num6 = 0; num6 < _staleInstanceIds.Count; num6++)
				{
					ReleaseCommandGate(_staleInstanceIds[num6], "picker-destroyed-stale-or-sharing-disabled");
				}
				_staleInstanceIds.Clear();
				foreach (int key3 in _commandShareabilityDiagnosticState.Keys)
				{
					if (!_seenCommandCandidateIds.Contains(key3))
					{
						_staleInstanceIds.Add(key3);
					}
				}
				for (int num7 = 0; num7 < _staleInstanceIds.Count; num7++)
				{
					_commandShareabilityDiagnosticState.Remove(_staleInstanceIds[num7]);
				}
				_commandLifetimeUnknownLogged.RemoveWhere((int x) => !_seenCommandCandidateIds.Contains(x));
				foreach (PersonalMarkerDescriptor item3 in _markerRegistry.EndSweep())
				{
					PersonalMarkerIdentity identity = item3.Identity;
					if ((int)((PersonalMarkerIdentity)(ref identity)).Kind == 0)
					{
						HashSet<int> ordinaryRenderLogged = _ordinaryRenderLogged;
						identity = item3.Identity;
						ordinaryRenderLogged.Remove(((PersonalMarkerIdentity)(ref identity)).InstanceId);
					}
					else
					{
						identity = item3.Identity;
						int instanceId = ((PersonalMarkerIdentity)(ref identity)).InstanceId;
						string value3;
						string reason = (_commandRemovalReasons.TryGetValue(instanceId, out value3) ? value3 : "destroyed-or-untracked");
						LogCommandCleanup(instanceId, reason);
					}
				}
				_markers.Clear();
				_markers.AddRange(_nextOrdinaryMarkers);
				_commandMarkers.Clear();
				_commandMarkers.AddRange(_nextCommandMarkers);
			}
			finally
			{
				C2HitchDiagnostics.End(token, _markers.Count + _commandMarkers.Count, instancesList.Count);
				C2HitchDiagnostics.End(token2, _markers.Count + _commandMarkers.Count, instancesList.Count);
			}
		}

		private unsafe void OnMarkerRendered(MarkerRenderDiagnostic diagnostic)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			if (!_config.DiagnosticInfoEnabled)
			{
				return;
			}
			PersonalMarkerIdentity identity = diagnostic.Input.Identity;
			MarkerHudPlacement placement = diagnostic.Placement;
			MarkerHudMode mode = ((MarkerHudPlacement)(ref placement)).Mode;
			MarkerHudEdge edge = ((MarkerHudPlacement)(ref placement)).Edge;
			int laneSlot = ((MarkerHudPlacement)(ref placement)).LaneSlot;
			int railSlot = ((MarkerHudPlacement)(ref placement)).RailSlot;
			bool hudRelocated = ((MarkerHudPlacement)(ref placement)).HudRelocated;
			bool messageHudRelocated = ((MarkerHudPlacement)(ref placement)).MessageHudRelocated;
			bool collisionRelocated = ((MarkerHudPlacement)(ref placement)).CollisionRelocated;
			bool usedMeasurementFallback = diagnostic.UsedMeasurementFallback;
			float labelPreferredWidth = diagnostic.LabelPreferredWidth;
			MarkerHudVisualFootprint footprint = diagnostic.Footprint;
			MarkerHudDiagnosticState val = MarkerRuntimeHotPathPolicy.BuildHudDiagnosticState(mode, edge, laneSlot, railSlot, hudRelocated, messageHudRelocated, collisionRelocated, usedMeasurementFallback, labelPreferredWidth, ((MarkerHudVisualFootprint)(ref footprint)).Width);
			MarkerHudDiagnosticState value;
			bool flag = !_markerProjectionDiagnosticState.TryGetValue(diagnostic.ClusterKey, out value) || !((MarkerHudDiagnosticState)(ref value)).Equals(val);
			if (flag)
			{
				_markerProjectionDiagnosticState[diagnostic.ClusterKey] = val;
			}
			bool flag2 = (int)((PersonalMarkerIdentity)(ref identity)).Kind == 0 && _ordinaryRenderLogged.Add(((PersonalMarkerIdentity)(ref identity)).InstanceId);
			if (flag || flag2)
			{
				string text = (((int)((MarkerHudPlacement)(ref placement)).Mode == 0) ? "onscreen" : "edge");
				string text2 = FormatEdge(((MarkerHudPlacement)(ref placement)).Edge);
				if (flag)
				{
					MarkerHudRect finalRect = ((MarkerHudPlacement)(ref placement)).FinalRect;
					string[] obj = new string[39]
					{
						"ISF_MARKER_HUD clusterKey=",
						diagnostic.ClusterKey.ToString(CultureInfo.InvariantCulture),
						" fingerprint=",
						diagnostic.MemberFingerprint,
						" total=",
						diagnostic.ClusterTotal.ToString(CultureInfo.InvariantCulture),
						" representative=",
						((object)(*(PersonalMarkerIdentity*)(&identity))/*cast due to .constrained prefix*/).ToString(),
						" mode=",
						text,
						" semantic=",
						diagnostic.SemanticText.Replace("\n", " | "),
						" edge=",
						text2,
						" stackSlot=",
						((MarkerHudPlacement)(ref placement)).StackSlot.ToString(CultureInfo.InvariantCulture),
						" laneSlot=",
						((MarkerHudPlacement)(ref placement)).LaneSlot.ToString(CultureInfo.InvariantCulture),
						" railSlot=",
						((MarkerHudPlacement)(ref placement)).RailSlot.ToString(CultureInfo.InvariantCulture),
						" rect=",
						FormatMarkerRect(finalRect),
						" hudRelocated=",
						((MarkerHudPlacement)(ref placement)).HudRelocated.ToString(),
						" messageHudRelocated=",
						((MarkerHudPlacement)(ref placement)).MessageHudRelocated.ToString(),
						" collisionRelocated=",
						((MarkerHudPlacement)(ref placement)).CollisionRelocated.ToString(),
						" anchorDisplacement=",
						MarkerHudNavigationPolicy.OnScreenAnchorDisplacement(diagnostic.SourceProjection, placement).ToString("F1", CultureInfo.InvariantCulture),
						" anchorDisplacementBound=",
						MarkerHudNavigationPolicy.GetMaxOnScreenAnchorDisplacement(diagnostic.Footprint, (float)Screen.width, (float)Screen.height).ToString("F1", CultureInfo.InvariantCulture),
						" labelPreferredWidth=",
						diagnostic.LabelPreferredWidth.ToString("F1", CultureInfo.InvariantCulture),
						" footprintWidth=",
						null,
						null,
						null,
						null
					};
					footprint = diagnostic.Footprint;
					obj[35] = ((MarkerHudVisualFootprint)(ref footprint)).Width.ToString("F1", CultureInfo.InvariantCulture);
					obj[36] = " measurementFallback=";
					obj[37] = diagnostic.UsedMeasurementFallback.ToString();
					obj[38] = " semanticModel=world-space-cluster renderer=canvas-tmp-ui-graphic";
					LogInfo(string.Concat(obj));
				}
				if (flag2)
				{
					LogInfo("ISF_MARKER_RENDER ordinary pickupInstanceId=" + ((PersonalMarkerIdentity)(ref identity)).InstanceId.ToString(CultureInfo.InvariantCulture) + " clusterKey=" + diagnostic.ClusterKey.ToString(CultureInfo.InvariantCulture) + " fingerprint=" + diagnostic.MemberFingerprint + " total=" + diagnostic.ClusterTotal.ToString(CultureInfo.InvariantCulture) + " indicatorSource=" + MarkerPresentationPolicy.IndicatorAssetSourceToken + " style=" + MarkerPresentationPolicy.NativeHudStyleToken + " renderer=canvas-tmp-ui-graphic mode=" + text + " edge=" + text2);
				}
			}
		}

		private static string FormatEdge(MarkerHudEdge edge)
		{
			//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
			return (edge - 1) switch
			{
				0 => "left", 
				1 => "right", 
				2 => "top", 
				3 => "bottom", 
				_ => "none", 
			};
		}

		private static bool SameDiagnosticRect(MarkerHudRect left, MarkerHudRect right)
		{
			if (Math.Abs(((MarkerHudRect)(ref left)).Left - ((MarkerHudRect)(ref right)).Left) < 0.5f && Math.Abs(((MarkerHudRect)(ref left)).Right - ((MarkerHudRect)(ref right)).Right) < 0.5f && Math.Abs(((MarkerHudRect)(ref left)).Bottom - ((MarkerHudRect)(ref right)).Bottom) < 0.5f)
			{
				return Math.Abs(((MarkerHudRect)(ref left)).Top - ((MarkerHudRect)(ref right)).Top) < 0.5f;
			}
			return false;
		}

		private static string FormatMarkerRect(MarkerHudRect rect)
		{
			return ((MarkerHudRect)(ref rect)).Left.ToString("F1", CultureInfo.InvariantCulture) + "," + ((MarkerHudRect)(ref rect)).Bottom.ToString("F1", CultureInfo.InvariantCulture) + "," + ((MarkerHudRect)(ref rect)).Right.ToString("F1", CultureInfo.InvariantCulture) + "," + ((MarkerHudRect)(ref rect)).Top.ToString("F1", CultureInfo.InvariantCulture);
		}

		private static bool ShouldShowMarker(ParticipantState[] localStates, bool[] collected)
		{
			for (int i = 0; i < localStates.Length; i++)
			{
				if (ProjectionPolicy.ShowPersonalMarker(true, localStates[i], collected[i], false))
				{
					return true;
				}
			}
			return false;
		}

		private CharacterMaster[] GetLocalMastersSnapshot()
		{
			if (_localMastersFrame == Time.frameCount)
			{
				return _cachedLocalMasters;
			}
			_localMastersFrame = Time.frameCount;
			LocalParticipantResolver.FillLocalMasters(_localMasterBuffer);
			if (_cachedLocalMasters.Length != _localMasterBuffer.Count)
			{
				_cachedLocalMasters = (CharacterMaster[])(object)new CharacterMaster[_localMasterBuffer.Count];
			}
			for (int i = 0; i < _localMasterBuffer.Count; i++)
			{
				_cachedLocalMasters[i] = _localMasterBuffer[i];
			}
			return _cachedLocalMasters;
		}

		private void EnsureParticipantBuffers(int count)
		{
			if (_localStateBuffer.Length != count)
			{
				_localStateBuffer = (ParticipantState[])(object)new ParticipantState[count];
			}
			if (_collectedBuffer.Length != count)
			{
				_collectedBuffer = new bool[count];
			}
			if (_localPickedStateBuffer.Length != count)
			{
				_localPickedStateBuffer = new bool?[count];
			}
		}

		private void NormalizeUpstreamForGate(GenericPickupController pickup)
		{
			try
			{
				_upstreamNormalizationDepth++;
				_upstream.NormalizeUpstreamVisualSubtree(pickup);
			}
			finally
			{
				_upstreamNormalizationDepth--;
			}
		}

		private void ReleaseGate(int instanceId)
		{
			if (_gates.TryGetValue(instanceId, out LocalPickupPresentationGate value))
			{
				if ((Object)(object)value != (Object)null)
				{
					value.Restore();
					Object.Destroy((Object)(object)value);
				}
				_gates.Remove(instanceId);
			}
		}

		private void ApplyLocalCommandPresentation(PickupPickerController picker, LocalCommandPresentationDecision decision)
		{
			int instanceID = ((Object)picker).GetInstanceID();
			if (((LocalCommandPresentationDecision)(ref decision)).SuppressWorldPresentation)
			{
				if (!_commandGates.TryGetValue(instanceID, out LocalCommandPresentationGate value) || (Object)(object)value == (Object)null)
				{
					value = ((Component)picker).gameObject.GetComponent<LocalCommandPresentationGate>() ?? ((Component)picker).gameObject.AddComponent<LocalCommandPresentationGate>();
					_commandGates[instanceID] = value;
				}
				value.ApplyHidden();
				LogLocalCommandGateTransition(instanceID, visualSuppressed: true, "all-local-completed");
			}
			else
			{
				string reason = ((!((LocalCommandPresentationDecision)(ref decision)).AllLocalStateResolved) ? "local-state-unresolved" : (((LocalCommandPresentationDecision)(ref decision)).AnyLocalPending ? "local-participant-pending" : "not-all-local-completed"));
				ReleaseCommandGate(instanceID, reason);
			}
		}

		private void ReleaseCommandGate(int instanceId, string reason)
		{
			LocalCommandPresentationGate value;
			bool num = _commandGates.TryGetValue(instanceId, out value);
			if (num)
			{
				if ((Object)(object)value != (Object)null)
				{
					value.Restore();
					Object.Destroy((Object)(object)value);
				}
				_commandGates.Remove(instanceId);
			}
			bool value2;
			bool flag = _localCommandGateDiagnosticState.TryGetValue(instanceId, out value2) && value2;
			if (num || flag)
			{
				LogLocalCommandGateTransition(instanceId, visualSuppressed: false, reason);
			}
		}

		private void LogLocalCommandGateTransition(int instanceId, bool visualSuppressed, string reason)
		{
			if (_config.DiagnosticInfoEnabled && (!_localCommandGateDiagnosticState.TryGetValue(instanceId, out var value) || value != visualSuppressed))
			{
				_localCommandGateDiagnosticState[instanceId] = visualSuppressed;
				LogInfo("ISF_C20_LOCAL_COMMAND_GATE picker=" + instanceId.ToString(CultureInfo.InvariantCulture) + " allLocalCompleted=" + visualSuppressed.ToString().ToLowerInvariant() + " visualSuppressed=" + visualSuppressed.ToString().ToLowerInvariant() + " reason=" + reason);
			}
		}

		private void LogLocalVisualGateTransition(GenericPickupController pickup, int collectedCount, int localCount, bool visualSuppressed)
		{
			if (_config.DiagnosticInfoEnabled && !((Object)(object)pickup == (Object)null))
			{
				string text = collectedCount.ToString(CultureInfo.InvariantCulture) + "/" + localCount.ToString(CultureInfo.InvariantCulture) + ":" + visualSuppressed;
				int instanceID = ((Object)pickup).GetInstanceID();
				if (!_localPickupVisualDiagnosticState.TryGetValue(instanceID, out string value) || !string.Equals(value, text, StringComparison.Ordinal))
				{
					_localPickupVisualDiagnosticState[instanceID] = text;
					LogInfo("ISF_C20_LOCAL_PICKUP_GATE pickup=" + instanceID.ToString(CultureInfo.InvariantCulture) + " localMaster=process localCollected=" + collectedCount.ToString(CultureInfo.InvariantCulture) + "/" + localCount.ToString(CultureInfo.InvariantCulture) + " visualSuppressed=" + visualSuppressed.ToString().ToLowerInvariant() + " interactionSuppressed=participant-specific action=visual-state reason=" + (visualSuppressed ? "all-local-collected" : "local-participant-still-needs-pickup"));
				}
			}
		}

		private void LogLocalInteractionGateTransition(GenericPickupController pickup, CharacterMaster master, bool collected, bool interactionSuppressed)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (_config.DiagnosticInfoEnabled && !((Object)(object)pickup == (Object)null) && !((Object)(object)master == (Object)null))
			{
				int instanceID = ((Object)pickup).GetInstanceID();
				int instanceID2 = ((Object)master).GetInstanceID();
				long key = (long)(((ulong)(uint)instanceID << 32) | (uint)instanceID2);
				if (!_localPickupInteractionDiagnosticState.TryGetValue(key, out var value) || value != interactionSuppressed)
				{
					_localPickupInteractionDiagnosticState[key] = interactionSuppressed;
					string[] obj = new string[12]
					{
						"ISF_C20_LOCAL_PICKUP_GATE pickup=",
						instanceID.ToString(CultureInfo.InvariantCulture),
						" localMaster=masterNetId=",
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					NetworkInstanceId netId = ((NetworkBehaviour)master).netId;
					obj[3] = ((NetworkInstanceId)(ref netId)).Value.ToString(CultureInfo.InvariantCulture);
					obj[4] = " localCollected=";
					obj[5] = collected.ToString().ToLowerInvariant();
					obj[6] = " visualSuppressed=";
					obj[7] = _gates.ContainsKey(instanceID).ToString().ToLowerInvariant();
					obj[8] = " interactionSuppressed=";
					obj[9] = interactionSuppressed.ToString().ToLowerInvariant();
					obj[10] = " action=interactability-state reason=";
					obj[11] = (interactionSuppressed ? "local-collector-already-collected" : "local-participant-not-collected");
					LogInfo(string.Concat(obj));
				}
			}
		}

		private static bool TryGetFiniteCameraPosition(Camera camera, out Vector3 cameraPosition)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			cameraPosition = default(Vector3);
			try
			{
				cameraPosition = ((Component)camera).transform.position;
				return MarkerPresentationPolicy.AreCoordinatesFinite(cameraPosition.x, cameraPosition.y, cameraPosition.z);
			}
			catch
			{
				return false;
			}
		}

		private static bool TryResolveOrdinaryMarkerTarget(GenericPickupController pickup, out Vector3 worldPosition, out string invalidReason)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			worldPosition = default(Vector3);
			invalidReason = string.Empty;
			if ((Object)(object)pickup == (Object)null)
			{
				invalidReason = "destroyed-or-missing";
				return false;
			}
			try
			{
				if ((Object)(object)((Component)pickup).gameObject == (Object)null || !((Component)pickup).gameObject.activeInHierarchy)
				{
					invalidReason = "inactive-or-removed";
					return false;
				}
				if (PickupCatalog.GetPickupDef(pickup.pickup.pickupIndex) == null)
				{
					invalidReason = "pickup-def-unresolved";
					return false;
				}
				worldPosition = ((Component)pickup).transform.position;
				invalidReason = MarkerPresentationPolicy.ValidateWorldPosition(worldPosition.x, worldPosition.y, worldPosition.z);
				return string.IsNullOrEmpty(invalidReason);
			}
			catch
			{
				invalidReason = "target-resolution-failed";
				return false;
			}
		}

		private static bool TryResolveCommandMarkerTarget(PickupPickerController picker, out Vector3 worldPosition, out string invalidReason)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			worldPosition = default(Vector3);
			invalidReason = string.Empty;
			if ((Object)(object)picker == (Object)null)
			{
				invalidReason = "destroyed-or-missing";
				return false;
			}
			try
			{
				if ((Object)(object)((Component)picker).gameObject == (Object)null || !((Component)picker).gameObject.activeInHierarchy)
				{
					invalidReason = "inactive-or-removed";
					return false;
				}
				worldPosition = ((Component)picker).transform.position;
				invalidReason = MarkerPresentationPolicy.ValidateWorldPosition(worldPosition.x, worldPosition.y, worldPosition.z);
				return string.IsNullOrEmpty(invalidReason);
			}
			catch
			{
				invalidReason = "target-resolution-failed";
				return false;
			}
		}

		private static bool TryResolvePresentationDistance(Vector3 cameraPosition, Vector3 worldPosition, out int roundedDistanceMeters, out string invalidReason)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			roundedDistanceMeters = 0;
			invalidReason = string.Empty;
			float num = Vector3.Distance(cameraPosition, worldPosition);
			invalidReason = MarkerPresentationPolicy.ValidatePresentationDistance(num);
			if (!string.IsNullOrEmpty(invalidReason))
			{
				return false;
			}
			roundedDistanceMeters = Mathf.Max(0, Mathf.RoundToInt(num));
			return true;
		}

		private void RemoveOrdinaryMarkerNow(PersonalPickupMarker marker, string reason)
		{
			_markers.Remove(marker);
			_markerR