Decompiled source of ItemShareFix v1.0.0

plugins/ItemShareFix/ItemShareFix.Core.dll

Decompiled 8 hours 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.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ItemShareFix.Core")]
[assembly: AssemblyTitle("ItemShareFix.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ItemShareFix.Core
{
	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(IEnumerable<bool?>? optionShareability)
		{
			if (optionShareability == null)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Unresolved);
			}
			bool?[] array = optionShareability.ToArray();
			if (array.Length == 0 || array.Any((bool? x) => !x.HasValue))
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Unresolved);
			}
			bool flag = array.Any((bool? x) => x == true);
			bool flag2 = array.Any((bool? x) => x == false);
			if (flag && flag2)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.Mixed);
			}
			if (flag)
			{
				return new CommandShareabilityDecision(CommandShareabilityState.AllShareable);
			}
			return new CommandShareabilityDecision(CommandShareabilityState.AllUnshareable);
		}
	}
	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 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 = 11;

		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, 
				_ => 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 >= 11)
				{
					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(11, 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 }, 
				_ => 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
	}
	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 (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", 
				_ => "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);
			}
			MarkerClassKind[] array = choiceClasses.ToArray();
			if (array.Length == 0 || array.Any((MarkerClassKind x) => x == MarkerClassKind.Unknown))
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedReadableClassLabel(MarkerClassKind.Unknown, language), exactClass: false);
			}
			MarkerClassKind[] array2 = array.Distinct().ToArray();
			if (array2.Length != 1)
			{
				return new CommandClassPresentation(MarkerClassKind.Unknown, LocalizedReadableClassLabel(MarkerClassKind.Unknown, language), exactClass: false);
			}
			MarkerClassKind markerClassKind = array2[0];
			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 = 11;

		public const int MaxCompactLifetimePresentationGroups = 22;

		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 >= 11)
					{
						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(22, array.Length * 2));
			for (int k = 0; k < array.Length; k++)
			{
				if (list.Count >= 22)
				{
					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 < 22)
				{
					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 < 22)
				{
					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 AppendLifetimeSummary(StringBuilder builder, MarkerSemanticCluster cluster, bool showTemporaryCount, bool russian)
		{
			string value = MarkerLifetimePolicy.BuildSummaryLine(cluster.LifetimeSummary, cluster.TemporaryPhysicalMemberCount, showTemporaryCount, russian);
			if (!string.IsNullOrEmpty(value))
			{
				if (builder.Length > 0)
				{
					builder.Append('\n');
				}
				builder.Append(value);
			}
		}

		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(_orderedClusters[i].WorldAnchor, _orderedClusters[j].WorldAnchor) <= num)
						};
					}
				}
			}
		}

		private void AdvanceExistingPairs(double nowSeconds)
		{
			float num = 144f;
			float num2 = 256f;
			foreach (KeyValuePair<PairKey, PairState> pairState in _pairStates)
			{
				MarkerSemanticCluster markerSemanticCluster = FindCluster(pairState.Key.A);
				MarkerSemanticCluster markerSemanticCluster2 = FindCluster(pairState.Key.B);
				if (markerSemanticCluster == null || markerSemanticCluster2 == null)
				{
					continue;
				}
				float num3 = MarkerWorldPoint.DistanceSquared(markerSemanticCluster.WorldAnchor, markerSemanticCluster2.WorldAnchor);
				PairState value = pairState.Value;
				if (value.Linked)
				{
					if (num3 <= num2)
					{
						value.Pending = false;
					}
					else
					{
						AdvancePending(value, target: false, nowSeconds);
					}
				}
				else if (num3 >= num)
				{
					value.Pending = false;
				}
				else
				{
					AdvancePending(value, target: true, nowSeconds);
				}
			}
		}

		private static void AdvancePending(PairState state, bool target, double nowSeconds)
		{
			if (!state.Pending || state.PendingTarget != target)
			{
				state.Pending = true;
				state.PendingTarget = target;
				state.PendingSince = nowSeconds;
			}
			else if (!(nowSeconds - state.PendingSince < 0.35))
			{
				state.Linked = target;
				state.Pending = false;
			}
		}

		private void PrunePairStates()
		{
			_stalePairs.Clear();
			foreach (PairKey key in _pairStates.Keys)
			{
				if (FindCluster(key.A) == null || FindCluster(key.B) == null)
				{
					_stalePairs.Add(key);
				}
			}
			for (int i = 0; i < _stalePairs.Count; i++)
			{
				_pairStates.Remove(_stalePairs[i]);
			}
		}

		private MarkerSemanticCluster? FindCluster(long key)
		{
			int num = 0;
			int num2 = _orderedClusters.Count - 1;
			while (num <= num2)
			{
				int num3 = num + (num2 - num >> 1);
				long stableKey = _orderedClusters[num3].StableKey;
				if (stableKey == key)
				{
					return _orderedClusters[num3];
				}
				if (stableKey < key)
				{
					num = num3 + 1;
				}
				else
				{
					num2 = num3 - 1;
				}
			}
			return null;
		}

		private List<MarkerDenseAreaPresentationNode> BuildPresentationNodes()
		{
			List<MarkerDenseAreaPresentationNode> list = new List<MarkerDenseAreaPresentationNode>(_orderedClusters.Count);
			if (_orderedClusters.Count == 0)
			{
				return list;
			}
			int[] array = new int[_orderedClusters.Count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = i;
			}
			foreach (KeyValuePair<PairKey, PairState> pairState in _pairStates)
			{
				if (pairState.Value.Linked)
				{
					int num = IndexOfCluster(pairState.Key.A);
					int num2 = IndexOfCluster(pairState.Key.B);
					if (num >= 0 && num2 >= 0)
					{
						Union(array, num, num2);
					}
				}
			}
			Dictionary<int, List<MarkerSemanticCluster>> dictionary = new Dictionary<int, List<MarkerSemanticCluster>>();
			for (int j = 0; j < _orderedClusters.Count; j++)
			{
				int key = Find(array, j);
				if (!dictionary.TryGetValue(key, out var value))
				{
					value = new List<MarkerSemanticCluster>();
					dictionary.Add(key, value);
				}
				value.Add(_orderedClusters[j]);
			}
			HashSet<long> claimedPreviousOwners = new HashSet<long>();
			foreach (List<MarkerSemanticCluster> value2 in dictionary.Values)
			{
				value2.Sort((MarkerSemanticCluster left, MarkerSemanticCluster right) => left.StableKey.CompareTo(right.StableKey));
				long[] memberKeys = CollectMemberKeys(value2);
				if (value2.Count < 2)
				{
					if (TryClaimPreviousOwnerKey(memberKeys, claimedPreviousOwners, out var ownerKey))
					{
						MarkerSemanticCluster presentationCluster = BuildSummaryCluster(ownerKey, value2, memberKeys);
						list.Add(new MarkerDenseAreaPresentationNode(ownerKey, isDenseSummary: true, new long[1] { value2[0].StableKey }, presentationCluster));
					}
					else
					{
						MarkerSemanticCluster markerSemanticCluster = value2[0];
						list.Add(new MarkerDenseAreaPresentationNode(markerSemanticCluster.StableKey, isDenseSummary: false, new long[1] { markerSemanticCluster.StableKey }, markerSemanticCluster));
					}
				}
				else
				{
					long num3 = ResolvePersistentOwnerKey(memberKeys, claimedPreviousOwners);
					MarkerSemanticCluster presentationCluster2 = BuildSummaryCluster(num3, value2, memberKeys);
					long[] array2 = new long[value2.Count];
					for (int num4 = 0; num4 < value2.Count; num4++)
					{
						array2[num4] = value2[num4].StableKey;
					}
					list.Add(new MarkerDenseAreaPresentationNode(num3, isDenseSummary: true, array2, presentationCluster2));
				}
			}
			list.Sort((MarkerDenseAreaPresentationNode left, MarkerDenseAreaPresentationNode right) => left.StableKey.CompareTo(right.StableKey));
			return list;
		}

		private long ResolvePersistentOwnerKey(long[] memberKeys, HashSet<long> claimedPreviousOwners)
		{
			if (TryClaimPreviousOwnerKey(memberKeys, claimedPreviousOwners, out var ownerKey))
			{
				return ownerKey;
			}
			long num = -MarkerWorldClusterTracker.StableClusterKey(memberKeys);
			if (num == 0L || num == long.MinValue)
			{
				num = -1L;
			}
			claimedPreviousOwners.Add(num);
			return num;
		}

		private bool TryClaimPreviousOwnerKey(long[] memberKeys, HashSet<long> claimedPreviousOwners, out long ownerKey)
		{
			long num = 0L;
			int num2 = 0;
			for (int i = 0; i < _previousDenseOwners.Count; i++)
			{
				PreviousDenseOwner previousDenseOwner = _previousDenseOwners[i];
				if (!claimedPreviousOwners.Contains(previousDenseOwner.OwnerKey))
				{
					int num3 = CountOverlap(previousDenseOwner.MemberKeys, memberKeys);
					if (num3 > num2 || (num3 == num2 && num3 > 0 && previousDenseOwner.OwnerKey < num))
					{
						num2 = num3;
						num = previousDenseOwner.OwnerKey;
					}
				}
			}
			if (num2 > 0)
			{
				claimedPreviousOwners.Add(num);
				ownerKey = num;
				return true;
			}
			ownerKey = 0L;
			return false;
		}

		private static MarkerSemanticCluster BuildSummaryCluster(long ownerKey, IReadOnlyList<MarkerSemanticCluster> clusters, long[] memberKeys)
		{
			Dictionary<MarkerSemanticCategory, int> dictionary = new Dictionary<MarkerSemanticCategory, int>();
			Dictionary<MarkerItemLifetimeKey, MutableAggregate> dictionary2 = new Dictionary<MarkerItemLifetimeKey, MutableAggregate>();
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			for (int i = 0; i < clusters.Count; i++)
			{
				MarkerSemanticCluster markerSemanticCluster = clusters[i];
				int num8 = Math.Max(1, markerSemanticCluster.TotalCount);
				num += (double)(markerSemanticCluster.WorldAnchor.X * (float)num8);
				num2 += (double)(markerSemanticCluster.WorldAnchor.Y * (float)num8);
				num3 += (double)(markerSemanticCluster.WorldAnchor.Z * (float)num8);
				num4 += num8;
				num5 += markerSemanticCluster.TemporaryPhysicalMemberCount;
				num6 += markerSemanticCluster.MixedLifetimeMemberCount;
				num7 += markerSemanticCluster.UnknownLifetimeMemberCount;
				for (int j = 0; j < markerSemanticCluster.Composition.Count; j++)
				{
					MarkerCategoryCount markerCategoryCount = markerSemanticCluster.Composition[j];
					dictionary.TryGetValue(markerCategoryCount.Category, out var value);
					dictionary[markerCategoryCount.Category] = value + markerCategoryCount.Count;
				}
				for (int k = 0; k < markerSemanticCluster.ItemRows.Count; k++)
				{
					MarkerItemAggregate markerItemAggregate = markerSemanticCluster.ItemRows[k];
					MarkerItemLifetimeKey key = new MarkerItemLifetimeKey(markerItemAggregate.ItemIdentity, markerItemAggregate.Lifetime);
					if (!dictionary2.TryGetValue(key, out var value2))
					{
						value2 = new MutableAggregate(markerItemAggregate.ItemIdentity, markerItemAggregate.LocalizedName, markerItemAggregate.Category, markerItemAggregate.Lifetime);
						dictionary2.Add(key, value2);
					}
					value2.Count += markerItemAggregate.Count;
				}
			}
			List<MarkerCategoryCount> list = new List<MarkerCategoryCount>(dictionary.Count);
			foreach (KeyValuePair<MarkerSemanticCategory, int> item in dictionary)
			{
				list.Add(new MarkerCategoryCount(item.Key, item.Value));
			}
			list.Sort((MarkerCategoryCount left, MarkerCategoryCount right) => MarkerSemanticCategoryPolicy.StableOrder(left.Category).CompareTo(MarkerSemanticCategoryPolicy.StableOrder(right.Category)));
			List<MarkerItemAggregate> list2 = new List<MarkerItemAggregate>(dictionary2.Count);
			foreach (MutableAggregate value3 in dictionary2.Values)
			{
				list2.Add(new MarkerItemAggregate(value3.ItemIdentity, value

plugins/ItemShareFix/ItemShareFix.dll

Decompiled 8 hours 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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemShareFix.Core;
using Microsoft.CodeAnalysis;
using RoR2;
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.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ItemShareFix")]
[assembly: AssemblyTitle("ItemShareFix")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ItemShareFix
{
	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 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;

		public ClientPresentationCoordinator(PluginConfig config, UpstreamBridge upstream, ManualLogSource log)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			_config = config;
			_upstream = upstream;
			_log = log;
			_localHudProbe = new LocalHudPresentationProbe(_performance);
			_hudRenderer = new NativeHudMarkerRenderer(log, _performance);
			_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)
			{
				if (!_config.PersonalMarkersEnabled.Value)
				{
					_hudRenderer.Clear();
				}
				RequestRefresh();
			}
			else if (sender == _config.ShareTemporaryItems)
			{
				RequestRefresh();
			}
		}

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

		public void RequestRefresh()
		{
			_refreshRequested = true;
		}

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

		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 || !_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)
			{
				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.DiagnosticLogging.Value && _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_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0433: 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_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: 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_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: 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_03e8: Unknown result type (might be due to invalid IL or missing references)
			_performance.RecordRenderFrame();
			bool flag = _config.Enabled.Value && _config.PersonalMarkersEnabled.Value && (_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();
				return;
			}
			MaybeEmitPerformanceSummary(_lastPerformanceMarkerCount = _markers.Count + _commandMarkers.Count);
			string reason;
			bool flag2 = _localHudProbe.TryGetBlockingModal(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.TryGetVisibleMessageHudRect(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));
			}
			Camera presentationCamera = GetPresentationCamera();
			if ((Object)(object)presentationCamera == (Object)null || !TryGetFiniteCameraPosition(presentationCamera, out var cameraPosition))
			{
				_hudRenderer.Clear();
				return;
			}
			MarkerLanguage val = CurrentMarkerLanguage();
			_renderInputs.Clear();
			int num = 0;
			while (num < _markers.Count)
			{
				PersonalPickupMarker personalPickupMarker = _markers[num];
				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, val), personalPickupMarker.ItemSemanticKey, personalPickupMarker.ClassName, personalPickupMarker.Kind, personalPickupMarker.TextColor, ResolvePickupIcon(personalPickupMarker.Pickup), personalPickupMarker.Lifetime));
				num++;
			}
			int num2 = 0;
			while (num2 < _commandMarkers.Count)
			{
				PersonalCommandMarker personalCommandMarker = _commandMarkers[num2];
				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, val), personalCommandMarker.ItemSemanticKey, personalCommandMarker.ClassName, personalCommandMarker.Kind, personalCommandMarker.TextColor, null, personalCommandMarker.Lifetime));
				num2++;
			}
			_hudRenderer.Render(presentationCamera, _renderInputs, _config.MarkerSettingsSnapshot(), _config.MarkerVisualSettingsSnapshot(), val, OnMarkerRendered, _dynamicHudZones);
		}

		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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Invalid comparison between Unknown and I4
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0596: Unknown result type (might be due to invalid IL or missing references)
			//IL_059b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c2b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c30: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c34: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c5b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c60: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c43: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c48: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_069f: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Invalid comparison between Unknown and I4
			//IL_0788: Unknown result type (might be due to invalid IL or missing references)
			//IL_092b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0930: Unknown result type (might be due to invalid IL or missing references)
			//IL_0932: Unknown result type (might be due to invalid IL or missing references)
			//IL_0935: Invalid comparison between Unknown and I4
			//IL_0985: Unknown result type (might be due to invalid IL or missing references)
			//IL_0992: Unknown result type (might be due to invalid IL or missing references)
			//IL_099d: Unknown result type (might be due to invalid IL or missing references)
			//IL_09af: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b2: Invalid comparison between Unknown and I4
			//IL_089e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a50: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b7: 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;
			}
			ParticipantState[] array = localMastersSnapshot.Select(LocalParticipantResolver.ClassifyLocal).ToArray();
			MarkerLanguage val = CurrentMarkerLanguage();
			Camera presentationCamera = GetPresentationCamera();
			Vector3 cameraPosition = default(Vector3);
			bool flag = (Object)(object)presentationCamera != (Object)null && TryGetFiniteCameraPosition(presentationCamera, out cameraPosition);
			_markerRegistry.BeginSweep();
			List<PersonalPickupMarker> list = new List<PersonalPickupMarker>();
			HashSet<int> seenPickups = new HashSet<int>();
			HashSet<int> hashSet = new HashSet<int>(_markers.Select((PersonalPickupMarker x) => x.InstanceId));
			int num = 0;
			int roundedDistanceMeters;
			foreach (GenericPickupController pickup in InstanceTracker.GetInstancesList<GenericPickupController>())
			{
				if ((Object)(object)pickup == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)pickup).GetInstanceID();
				if (!TryResolveOrdinaryMarkerTarget(pickup, out Vector3 worldPosition, out string invalidReason) || (flag && !TryResolvePresentationDistance(cameraPosition, worldPosition, out roundedDistanceMeters, out invalidReason)))
				{
					ReleaseGate(instanceID);
					_markerRegistry.Remove((PersonalMarkerKind)0, instanceID);
					_ordinaryRenderLogged.Remove(instanceID);
					if (hashSet.Contains(instanceID))
					{
						LogOrdinaryCleanup(instanceID, invalidReason);
					}
				}
				else
				{
					if (!_upstream.IsShareable(pickup))
					{
						continue;
					}
					seenPickups.Add(instanceID);
					bool[] array2 = localMastersSnapshot.Select((CharacterMaster master) => _upstream.HasCollected(pickup, master)).ToArray();
					int num2 = array2.Count((bool result) => result);
					bool flag2 = LocalPickupSuppressionPolicy.ShouldSuppressProcessVisual(_config.PersonalPickupVisibilityRepairEnabled.Value, _upstream.HideCollectedOrbsEnabled, array2.Length, num2);
					if (flag2)
					{
						if (!_gates.TryGetValue(instanceID, out LocalPickupPresentationGate value) || (Object)(object)value == (Object)null)
						{
							NormalizeUpstreamForGate(pickup);
							value = ((Component)pickup).gameObject.GetComponent<LocalPickupPresentationGate>() ?? ((Component)pickup).gameObject.AddComponent<LocalPickupPresentationGate>();
							_gates[instanceID] = value;
						}
						value.ApplyHidden();
					}
					else
					{
						ReleaseGate(instanceID);
					}
					LogLocalVisualGateTransition(pickup, num2, array2.Length, flag2);
					UniquePickup pickup2 = pickup.pickup;
					MarkerLifetimeKind val2 = MarkerLifetimePolicy.FromTemporaryFlag(((UniquePickup)(ref pickup2)).isTempItem);
					if (_config.PersonalMarkersEnabled.Value && MarkerLifetimePolicy.IsMarkerEligible(val2, _config.ShareTemporaryItems.Value) && num < 64 && ShouldShowMarker(array, array2))
					{
						string text = MarkerPresentationPolicy.NormalizeLabel(PickupLabel(pickup, val), MarkerTextLocalization.FallbackSharedPickup(val));
						MarkerRuntimeMetadata markerRuntimeMetadata = ResolvePickupMarkerMetadata(pickup.pickup.pickupIndex);
						if ((int)_markerRegistry.MarkPending((PersonalMarkerKind)0, instanceID, text) != 3)
						{
							list.Add(new PersonalPickupMarker
							{
								InstanceId = instanceID,
								Pickup = pickup,
								Label = text,
								ItemSemanticKey = PickupSemanticKey(pickup),
								ClassName = markerRuntimeMetadata.ClassName,
								Kind = markerRuntimeMetadata.Kind,
								TextColor = markerRuntimeMetadata.TextColor,
								Lifetime = val2
							});
							num++;
						}
					}
				}
			}
			int[] array3 = _gates.Keys.Where((int x) => !seenPickups.Contains(x)).ToArray();
			for (roundedDistanceMeters = 0; roundedDistanceMeters < array3.Length; roundedDistanceMeters++)
			{
				int instanceId = array3[roundedDistanceMeters];
				ReleaseGate(instanceId);
			}
			List<PersonalCommandMarker> list2 = new List<PersonalCommandMarker>();
			HashSet<int> seenCommandCandidateIds = new HashSet<int>();
			_commandRemovalReasons.Clear();
			HashSet<int> hashSet2 = new HashSet<int>(_commandMarkers.Select((PersonalCommandMarker x) => x.InstanceId));
			int num3 = 0;
			if (_upstream.ShareCommandPicksEnabled)
			{
				foreach (PickupPickerController instances in InstanceTracker.GetInstancesList<PickupPickerController>())
				{
					if ((Object)(object)instances == (Object)null)
					{
						continue;
					}
					int instanceID2 = ((Object)instances).GetInstanceID();
					if (!_upstream.IsCommandCube(instances))
					{
						ReleaseCommandGate(instanceID2, "classifier-false");
						if (hashSet2.Contains(instanceID2))
						{
							_commandRemovalReasons[instanceID2] = "classifier-false";
						}
						continue;
					}
					seenCommandCandidateIds.Add(instanceID2);
					bool?[] array4 = new bool?[localMastersSnapshot.Length];
					bool flag3 = false;
					bool flag4 = true;
					for (int num4 = 0; num4 < localMastersSnapshot.Length; num4++)
					{
						if (!_upstream.TryHasCommandPicked(instances, localMastersSnapshot[num4], out var picked))
						{
							array4[num4] = null;
							flag4 = false;
							continue;
						}
						array4[num4] = picked;
						if (ProjectionPolicy.ShowPersonalMarker(true, array[num4], picked, false))
						{
							flag3 = true;
						}
					}
					LocalCommandPresentationDecision decision = LocalCommandPresentationPolicy.Evaluate((IReadOnlyList<bool?>)array4);
					ApplyLocalCommandPresentation(instances, decision);
					if (!_config.PersonalMarkersEnabled.Value)
					{
						if (hashSet2.Contains(instanceID2))
						{
							_commandRemovalReasons[instanceID2] = "markers-disabled";
						}
						continue;
					}
					if (!TryResolveCommandMarkerTarget(instances, out Vector3 worldPosition2, out string invalidReason2) || (flag && !TryResolvePresentationDistance(cameraPosition, worldPosition2, out roundedDistanceMeters, out invalidReason2)))
					{
						_markerRegistry.Remove((PersonalMarkerKind)1, instanceID2);
						if (hashSet2.Contains(instanceID2))
						{
							LogCommandCleanup(instanceID2, invalidReason2);
						}
						continue;
					}
					bool flag5 = flag3 || flag4;
					if (num3 >= 32 || !MarkerPresentationPolicy.ShouldTrackCommandMarker(_config.PersonalMarkersEnabled.Value, _upstream.IsIndividualMode, _upstream.ShareCommandPicksEnabled, true, flag5, flag3))
					{
						if (hashSet2.Contains(instanceID2))
						{
							_commandRemovalReasons[instanceID2] = (flag4 ? "local-completed" : "local-state-unresolved");
						}
						continue;
					}
					string optionSource;
					int resolvedOptionCount;
					bool sourceDisagreement;
					CommandShareabilityDecision shareability;
					MarkerRuntimeMetadata markerRuntimeMetadata2 = ResolveCommandMarkerMetadata(instances, val, out optionSource, out resolvedOptionCount, out sourceDisagreement, out shareability);
					MarkerLifetimeKind lifetime = (MarkerLifetimeKind)3;
					int exactNestedAvailableOptionCount = 0;
					int unresolvedAvailableOptionCount = 0;
					_upstream.TryGetCommandChoiceLifetime(instances, out lifetime, out exactNestedAvailableOptionCount, out unresolvedAvailableOptionCount);
					string text2 = MarkerPresentationPolicy.NormalizeLabel(markerRuntimeMetadata2.Label, MarkerTextLocalization.FallbackCommandChoice(val));
					if ((int)lifetime == 3 && _commandLifetimeUnknownLogged.Add(instanceID2))
					{
						LogInfo("ISF_COMMAND_LIFETIME pickerInstanceId=" + instanceID2.ToString(CultureInfo.InvariantCulture) + " lifetime=Unknown exactNestedAvailable=" + exactNestedAvailableOptionCount.ToString(CultureInfo.InvariantCulture) + " unresolvedAvailable=" + unresolvedAvailableOptionCount.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(lifetime, _config.ShareTemporaryItems.Value))
					{
						_commandShareabilityDiagnosticState[instanceID2] = "temporary-sharing-disabled";
						if (hashSet2.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 (hashSet2.Contains(instanceID2))
						{
							_commandRemovalReasons[instanceID2] = ((CommandShareabilityDecision)(ref shareability)).FilterReason;
						}
						continue;
					}
					_commandShareabilityDiagnosticState[instanceID2] = ((CommandShareabilityDecision)(ref shareability)).DiagnosticToken + ":eligible";
					PersonalMarkerTransition val3 = _markerRegistry.MarkPending((PersonalMarkerKind)1, instanceID2, text2);
					if ((int)val3 != 3)
					{
						list2.Add(new PersonalCommandMarker
						{
							InstanceId = instanceID2,
							Picker = instances,
							Label = text2,
							ItemSemanticKey = "COMMAND:" + instanceID2.ToString(CultureInfo.InvariantCulture),
							ClassName = markerRuntimeMetadata2.ClassName,
							Kind = markerRuntimeMetadata2.Kind,
							TextColor = markerRuntimeMetadata2.TextColor,
							Lifetime = lifetime
						});
						num3++;
						if ((int)val3 == 1 || (int)val3 == 2)
						{
							string[] obj = new string[28]
							{
								"ISF_COMMAND_MARKER pending pickerInstanceId=",
								instanceID2.ToString(CultureInfo.InvariantCulture),
								" localPending=True providerHasState=",
								_upstream.HasPickerProviderState(instances).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*)(&lifetime))/*cast due to .constrained prefix*/).ToString();
							obj[24] = " lifetimeExactNested=";
							obj[25] = exactNestedAvailableOptionCount.ToString(CultureInfo.InvariantCulture);
							obj[26] = " lifetimeUnresolved=";
							obj[27] = unresolvedAvailableOptionCount.ToString(CultureInfo.InvariantCulture);
							LogInfo(string.Concat(obj));
						}
					}
				}
			}
			array3 = _commandGates.Keys.Where((int x) => !seenCommandCandidateIds.Contains(x)).ToArray();
			foreach (int instanceId2 in array3)
			{
				ReleaseCommandGate(instanceId2, "picker-destroyed-stale-or-sharing-disabled");
			}
			array3 = _commandShareabilityDiagnosticState.Keys.Where((int x) => !seenCommandCandidateIds.Contains(x)).ToArray();
			foreach (int key in array3)
			{
				_commandShareabilityDiagnosticState.Remove(key);
			}
			_commandLifetimeUnknownLogged.RemoveWhere((int x) => !seenCommandCandidateIds.Contains(x));
			foreach (PersonalMarkerDescriptor item in _markerRegistry.EndSweep())
			{
				PersonalMarkerIdentity identity = item.Identity;
				if ((int)((PersonalMarkerIdentity)(ref identity)).Kind == 0)
				{
					HashSet<int> ordinaryRenderLogged = _ordinaryRenderLogged;
					identity = item.Identity;
					ordinaryRenderLogged.Remove(((PersonalMarkerIdentity)(ref identity)).InstanceId);
				}
				else
				{
					identity = item.Identity;
					int instanceId3 = ((PersonalMarkerIdentity)(ref identity)).InstanceId;
					string value3;
					string reason = (_commandRemovalReasons.TryGetValue(instanceId3, out value3) ? value3 : "destroyed-or-untracked");
					LogCommandCleanup(instanceId3, reason);
				}
			}
			_markers.Clear();
			_markers.AddRange(list);
			_commandMarkers.Clear();
			_commandMarkers.AddRange(list2);
		}

		private unsafe void OnMarkerRendered(MarkerRenderDiagnostic diagnostic)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			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;
			_cachedLocalMasters = (from x in LocalParticipantResolver.GetLocalMasters()
				where (Object)(object)x != (Object)null
				select x).ToArray();
			return _cachedLocalMasters;
		}

		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.DiagnosticLogging.Value && (!_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.DiagnosticLogging.Value && !((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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (_config.DiagnosticLogging.Value && !((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);
			_markerRegistry.Remove((PersonalMarkerKind)0, marker.InstanceId);
			_ordinaryRenderLogged.Remove(marker.InstanceId);
			ReleaseGate(marker.InstanceId);
			LogOrdinaryCleanup(marker.InstanceId, reason);
		}

		private void RemoveCommandMarkerNow(PersonalCommandMarker marker, string reason)
		{
			_commandMarkers.Remove(marker);
			_markerRegistry.Remove((PersonalMarkerKind)1, marker.InstanceId);
			_commandShareabilityDiagnosticState.Remove(marker.InstanceId);
			LogCommandCleanup(marker.InstanceId, reason);
		}

		private void LogOrdinaryCleanup(int instanceId, string reason)
		{
			LogInfo("ISF_MARKER_CLEANUP ordinary pickupInstanceId=" + instanceId.ToString(CultureInfo.InvariantCulture) + " reason=" + reason);
		}

		private static Sprite? ResolvePickupIcon(GenericPickupController pickup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return PickupCatalog.GetPickupDef(pickup.pickup.pickupIndex)?.iconSprite;
			}
			catch
			{
				return null;
			}
		}

		private unsafe static string PickupSemanticKey(GenericPickupController pickup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PickupIndex pickupIndex = pickup.pickup.pickupIndex;
				PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
				if (pickupDef != null && !string.IsNullOrWhiteSpace(pickupDef.nameToken))
				{
					return "PICKUP:" + pickupDef.nameToken;
				}
				return "PICKUP_INDEX:" + ((object)(*(PickupIndex*)(&pickupIndex))/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return "PICKUP_INSTANCE:" + ((Object)pickup).GetInstanceID().ToString(CultureInfo.InvariantCulture);
			}
		}

		private static string PickupLabel(GenericPickupController pickup, MarkerLanguage language)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup.pickup.pickupIndex);
				if (pickupDef != null && !string.IsNullOrEmpty(pickupDef.nameToken))
				{
					string text = Language.GetString(pickupDef.nameToken);
					if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, pickupDef.nameToken, StringComparison.Ordinal))
					{
						return text;
					}
				}
			}
			catch
			{
			}
			return MarkerTextLocalization.FallbackSharedPickup(language);
		}

		private MarkerRuntimeMetadata ResolveCommandMarkerMetadata(PickupPickerController picker, MarkerLanguage language, out string optionSource, out int resolvedOptionCount, out bool sourceDisagreement, out CommandShareabilityDecision shareability)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Invalid comparison between Unknown and I4
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			optionSource = "unresolved";
			resolvedOptionCount = 0;
			sourceDisagreement = false;
			shareability = CommandShareabilityPolicy.Evaluate((IEnumerable<bool?>)Array.Empty<bool?>());
			if (!_upstream.TryGetCommandChoicePickupIndexes(picker, out PickupIndex[] pickupIndexes, out optionSource, out bool exactSource, out sourceDisagreement) || pickupIndexes.Length == 0)
			{
				CommandClassPresentation val = MarkerClassPolicy.ResolveCommandClassForReadablePresentation((IEnumerable<MarkerClassKind>)Array.Empty<MarkerClassKind>(), language);
				return new MarkerRuntimeMetadata(((CommandClassPresentation)(ref val)).Kind, MarkerClassPolicy.DiagnosticClassName(((CommandClassPresentation)(ref val)).Kind), ((CommandClassPresentation)(ref val)).Label, Color.white, exactClass: false);
			}
			resolvedOptionCount = pickupIndexes.Length;
			List<MarkerRuntimeMetadata> list = new List<MarkerRuntimeMetadata>(pickupIndexes.Length);
			List<bool?> list2 = new List<bool?>(pickupIndexes.Length);
			PickupIndex[] array = pickupIndexes;
			for (int i = 0; i < array.Length; i++)
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(array[i]);
				if (pickupDef == null)
				{
					list.Add(UnknownPickupMetadata());
					list2.Add(null);
				}
				else
				{
					list.Add(ResolvePickupMarkerMetadata(pickupDef));
					list2.Add(_upstream.TryIsShareable(pickupDef, out var shareable) ? new bool?(shareable) : ((bool?)null));
				}
			}
			shareability = (exactSource ? CommandShareabilityPolicy.Evaluate((IEnumerable<bool?>)list2) : CommandShareabilityPolicy.Evaluate((IEnumerable<bool?>)Array.Empty<bool?>()));
			CommandClassPresentation classPresentation = MarkerClassPolicy.ResolveCommandClassForReadablePresentation(list.Select((MarkerRuntimeMetadata x) => x.Kind), language);
			if (!((CommandClassPresentation)(ref classPresentation)).ExactClass)
			{
				Color textColor = (((int)((CommandClassPresentation)(ref classPresentation)).Kind == 9 && list.Count > 0) ? list[0].TextColor : Color.white);
				return new MarkerRuntimeMetadata(((CommandClassPresentation)(ref classPresentation)).Kind, MarkerClassPolicy.DiagnosticClassName(((CommandClassPresentation)(ref classPresentation)).Kind), ((CommandClassPresentation)(ref classPresentation)).Label, textColor, exactClass: false);
			}
			MarkerRuntimeMetadata[] array2 = list.Where((MarkerRuntimeMetadata x) => x.Kind == ((CommandClassPresentation)(ref classPresentation)).Kind).ToArray();
			Color textColor2 = ((array2.Length != 0) ? array2[0].TextColor : Color.white);
			return new MarkerRuntimeMetadata(((CommandClassPresentation)(ref classPresentation)).Kind, MarkerClassPolicy.DiagnosticClassName(((CommandClassPresentation)(ref classPresentation)).Kind), ((CommandClassPresentation)(ref classPresentation)).Label, textColor2, exactSource);
		}

		private static MarkerRuntimeMetadata ResolvePickupMarkerMetadata(PickupIndex pickupIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
				return (pickupDef != null) ? ResolvePickupMarkerMetadata(pickupDef) : UnknownPickupMetadata();
			}
			catch
			{
				return UnknownPickupMetadata();
			}
		}

		private static MarkerRuntimeMetadata ResolvePickupMarkerMetadata(PickupDef def)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				bool flag = (int)def.equipmentIndex != -1;
				bool flag2 = false;
				if (flag)
				{
					EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(def.equipmentIndex);
					flag2 = (Object)(object)equipmentDef != (Object)null && equipmentDef.isLunar;
				}
				MarkerClassKind val = MarkerClassPolicy.Classify(((object)Unsafe.As<ItemTier, ItemTier>(ref def.itemTier)/*cast due to .constrained prefix*/).ToString(), flag, flag2);
				return new MarkerRuntimeMetadata(val, MarkerClassPolicy.DiagnosticClassName(val), string.Empty, SanitizeMarkerColor(def.baseColor), (int)val > 0);
			}
			catch
			{
				return UnknownPickupMetadata();
			}
		}

		private static MarkerRuntimeMetadata UnknownPickupMetadata()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return new MarkerRuntimeMetadata((MarkerClassKind)0, MarkerClassPolicy.DiagnosticClassName((MarkerClassKind)0), string.Empty, Color.white, exactClass: false);
		}

		private static Color SanitizeMarkerColor(Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			if (float.IsNaN(color.r) || float.IsInfinity(color.r) || float.IsNaN(color.g) || float.IsInfinity(color.g) || float.IsNaN(color.b) || float.IsInfinity(color.b) || color.a <= 0.01f)
			{
				return Color.white;
			}
			color.a = 1f;
			return color;
		}

		private static string ColorEvidence(Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ColorUtility.ToHtmlStringRGB(SanitizeMarkerColor(color));
		}

		private static MarkerLanguage CurrentMarkerLanguage()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return MarkerTextLocalization.ResolveLanguage(Language.currentLanguageName);
			}
			catch
			{
				return (MarkerLanguage)0;
			}
		}

		private void LogCommandCleanup(int instanceId, string reason)
		{
			LogInfo("ISF_COMMAND_MARKER cleanup pickerInstanceId=" + instanceId.ToString(CultureInfo.InvariantCulture) + " reason=" + reason);
		}

		private Camera? GetPresentationCamera()
		{
			float unscaledTime = Time.unscaledTime;
			if ((Object)(object)_presentationCamera != (Object)null && (Object)(object)((Component)_presentationCamera).gameObject != (Object)null && ((Component)_presentationCamera).gameObject.activeInHierarchy && unscaledTime < _nextPresentationCameraRefresh)
			{
				return _presentationCamera;
			}
			_nextPresentationCameraRefresh = unscaledTime + 2f;
			try
			{
				_presentationCamera = Camera.main;
			}
			catch
			{
				_presentationCamera = null;
			}
			return _presentationCamera;
		}

		private void MaybeEmitPerformanceSummary(int markerCount)
		{
			if (_config.DiagnosticLogging.Value)
			{
				float unscaledTime = Time.unscaledTime;
				if (!(unscaledTime < _nextPerformanceSummary))
				{
					_nextPerformanceSummary = unscaledTime + 5f;
					EmitPerformanceSummary("periodic", markerCount, force: false);
				}
			}
		}

		private void EmitPerformanceSummary(string reason, int markerCount, bool force)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (_config.DiagnosticLogging.Value || force)
			{
				MarkerRuntimePerformanceSnapshot val = _performance.Snapshot();
				_log.LogInfo((object)("[ItemShareFix] ISF_MARKER_PERF_SUMMARY reason=" + reason + " markers=" + markerCount.ToString(CultureInfo.InvariantCulture) + " updates=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).UnityUpdateCalls.ToString(CultureInfo.InvariantCulture) + " renderFrames=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).RenderFrameCalls.ToString(CultureInfo.InvariantCulture) + " fullSolves=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).FullPlacementSolves.ToString(CultureInfo.InvariantCulture) + " singleFast=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).SingleMarkerFastPathCalls.ToString(CultureInfo.InvariantCulture) + " globalHudDiscovery=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).GlobalHudDiscoveries.ToString(CultureInfo.InvariantCulture) + " tmpMeasures=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).TmpPreferredMeasurements.ToString(CultureInfo.InvariantCulture) + " uiWrites=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).UiLayoutWrites.ToString(CultureInfo.InvariantCulture) + " diagnostics=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).DiagnosticRecords.ToString(CultureInfo.InvariantCulture) + " heavyMsTotal=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).HeavySolveMilliseconds.ToString("F3", CultureInfo.InvariantCulture) + " heavyMsMax=" + ((MarkerRuntimePerformanceSnapshot)(ref val)).MaxHeavySolveMilliseconds.ToString("F3", CultureInfo.InvariantCulture)));
			}
		}

		private void LogInfo(string message)
		{
			if (_config.DiagnosticLogging.Value)
			{
				_performance.RecordDiagnosticRecord();
				_log.LogInfo((object)("[ItemShareFix] " + message));
			}
		}

		private static int CurrentStageToken()
		{
			Run instance = Run.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return -1;
			}
			object member = ParticipantIdentityResolver.GetMember(instance, "stageClearCount");
			try
			{
				return (member != null) ? Convert.ToInt32(member, CultureInfo.InvariantCulture) : 0;
			}
			catch
			{
				return 0;
			}
		}
	}
	internal sealed class CompatibilityResult
	{
		public bool Supported { get; set; }

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

		public Assembly? ItemShareAssembly { get; set; }

		public Assembly? PickupShareApiAssembly { get; set; }

		public MethodInfo? DisconnectMethod { get; set; }
	}
	internal static class CompatibilityGuard
	{
		internal const string ExpectedItemShareSha256 = "48C25FE558CB095B2AC73836BE0563EBFDCD1C481AF9263D9D3740618F160F38";

		internal const string ExpectedPickupShareApiSha256 = "5EF4AC9457DB29BDA76C5DB110914EA14720ADE65DC6D5E48359B3DF8DED7F1D";

		public static CompatibilityResult Probe(ManualLogSource log)
		{
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly x) => string.Equals(x.GetName().Name, "ItemShare", StringComparison.Ordinal));
				if (assembly == null)
				{
					return Fail("ItemShare assembly is not loaded.");
				}
				if (assembly.GetName().Version?.ToString() != "1.7.1.0")
				{
					return Fail("Unsupported ItemShare assembly version: " + assembly.GetName().Version);
				}
				string text = HashAssembly(assembly);
				if (!string.Equals(text, "48C25FE558CB095B2AC73836BE0563EBFDCD1C481AF9263D9D3740618F160F38", StringComparison.OrdinalIgnoreCase))
				{
					return Fail("ItemShare.dll SHA-256 mismatch: " + text);
				}
				Assembly assembly2 = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly x) => string.Equals(x.GetName().Name, "PickupShareApi", StringComparison.Ordinal));
				if (assembly2 == null)
				{
					return Fail("PickupShareApi assembly is not loaded.");
				}
				if (assembly2.GetName().Version?.ToString() != "1.0.0.0")
				{
					return Fail("Unsupported PickupShareApi assembly version: " + assembly2.GetName().Version);
				}
				string text2 = HashAssembly(assembly2);
				if (!string.Equals(text2, "5EF4AC9457DB29BDA76C5DB110914EA14720ADE65DC6D5E48359B3DF8DED7F1D", StringComparison.OrdinalIgnoreCase))
				{
					return Fail("PickupShareApi.dll SHA-256 mismatch: " + text2);
				}
				Type type = assembly2.GetType("PickupShare.PickupShareApi", throwOnError: false);
				object obj = type?.GetProperty("ApiVersion", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				if (obj == null)
				{
					obj = type?.GetField("ApiVersion", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				}
				if (Convert.ToInt32(obj, CultureInfo.InvariantCulture) != 1)
				{
					return Fail("PickupShareApi contract is not ApiVersion 1.");
				}
				Type type2 = assembly.GetType("ItemShare.ItemSharePlugin", throwOnError: false);
				Type type3 = assembly.GetType("ItemShare.ClientPickMirror", throwOnError: false);
				Type type4 = assembly.GetType("ItemShare.ItemShareStateProvider", throwOnError: false);
				Type type5 = assembly2.GetType("PickupShare.PickupClassifier", throwOnError: false);
				if (type2 == null || type3 == null || type4 == null || type5 == null)
				{
					return Fail("Required exact ItemShare 1.7.1 / PickupShareApi 1.0.0 types are missing.");
				}
				string[] array = new string[7] { "Claims", "Distributed", "Choices", "_mode", "_hideCollectedOrbs", "_shareToDead", "_shareCommandPicks" };
				foreach (string text3 in array)
				{
					if (type2.GetField(text3, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) == null)
					{
						return Fail("Required ItemShare field missing: " + text3);
					}
				}
				(string, int, Type)[] array2 = new(string, int, Type)[11]
				{
					("OnAttemptGrant", 3, typeof(void)),
					("GrantIndividual", 5, typeof(void)),
					("GrantInstant", 5, typeof(void)),
					("GiveDirect", 3, typeof(bool)),
					("IsDown", 1, typeof(bool)),
					("OnPickupSelected", 3, typeof(void)),
					("IsShareable", 1, typeof(bool)),
					("BroadcastOrbState", 2, typeof(void)),
					("ApplyOrbVisibility", 2, typeof(void)),
					("LocalPlayersHaveTaken", 1, typeof(bool)),
					("RefreshOrbVisibility", 0, typeof(void))
				};
				for (int num = 0; num < array2.Length; num++)
				{
					(string Name, int ParameterCount, Type ReturnType) shape = array2[num];
					if ((from x in type2.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
						where string.Equals(x.Name, shape.Name, StringComparison.Ordinal) && x.GetParameters().Length == shape.ParameterCount && x.ReturnType == shape.ReturnType
						select x).ToArray().Length != 1)
					{
						return Fail("Required ItemShare method shape mismatch: " + shape.Name + "/" + shape.ParameterCount + " -> " + shape.ReturnType.Name);
					}
				}
				if (!HasExactOriginalDelegateHookShape(type2.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Single((MethodInfo x) => string.Equals(x.Name, "OnAttemptGrant", StringComparison.Ordinal) && x.GetParameters().Length == 3 && x.ReturnType == typeof(void)), typeof(GenericPickupController), typeof(CharacterBody)))
				{
					return Fail("ItemShare OnAttemptGrant exact orig/self/body delegate shape mismatch.");
				}
				if (!HasExactOriginalDelegateHookShape(type2.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Single((MethodInfo x) => string.Equals(x.Name, "OnPickupSelected", StringComparison.Ordinal) && x.GetParameters().Length == 3 && x.ReturnType == typeof(void)), typeof(PickupPickerController), typeof(int)))
				{
					return Fail("ItemShare OnPickupSelected exact orig/self/choiceIndex delegate shape mismatch.");
				}
				if (type4.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault((MethodInfo x) => string.Equals(x.Name, "TransferOrbState", StringComparison.Ordinal) && x.GetParameters().Length == 2 && x.ReturnType == typeof(bool)) == null)
				{
					return Fail("ItemShare provider TransferOrbState(int,int)->bool private shape missing.");
				}
				array = new string[2] { "Orbs", "Cubes" };
				foreach (string text4 in array)
				{
					if (type3.GetField(text4, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) == null)
					{
						return Fail("ItemShare ClientPickMirror." + text4 + " private shape missing.");
					}
				}
				MethodInfo method = type5.GetMethod("IsCommandCube", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(PickupPickerController) }, null);
				if (method == null || method.ReturnType != typeof(bool))
				{
					return Fail("PickupShareApi PickupClassifier.IsCommandCube(PickupPickerController)->bool shape missing.");
				}
				MethodInfo methodInfo = type?.GetMethod("HasPickerState", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(int) }, null);
				if (methodInfo == null || methodInfo.ReturnType != typeof(bool))
				{
					return Fail("PickupShareApi HasPickerState(int)->bool public shape missing.");
				}
				if (typeof(PickupPickerController).GetField("options", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) == null)
				{
					return Fail("RoR2 PickupPickerController.options exact choice-data field missing.");
				}
				FieldInfo fieldInfo = typeof(PickupPickerController).GetNestedType("Option", BindingFlags.Public | BindingFlags.NonPublic)?.GetField("pickup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (fieldInfo == null || fieldInfo.FieldType != typeof(UniquePickup))
				{
					return Fail("RoR2 PickupPickerController.Option.pickup : UniquePickup exact field missing.");
				}
				PropertyInfo property = typeof(UniquePickup).GetProperty("isTempItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property == null || property.PropertyType != typeof(bool) || property.GetIndexParameters().Length != 0)
				{
					return Fail("RoR2 UniquePickup.isTempItem : bool exact property missing.");
				}
				object obj2 = type?.GetProperty("HasProvider", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				string text5 = type?.GetProperty("ProviderName", BindingFlags.Static | BindingFlags.Public)?.GetValue(null)?.ToString();
				if (!(obj2 is bool) || !(bool)obj2)
				{
					return Fail("PickupShareApi has no registered provider; ItemShare must remain the sole provider.");
				}
				if (string.IsNullOrEmpty(text5) || !text5.StartsWith("ItemShare", StringComparison.Ordinal))
				{
					return Fail("PickupShareApi provider is not ItemShare: " + (text5 ?? "<null>"));
				}
				Assembly assembly3 = typeof(Run).Assembly;
				if (!HasStableNetworkUserIdShape(assembly3, out string reason))
				{
					return Fail("Stable NetworkUserId identity shape unsupported: " + reason);
				}
				Type type6 = assembly3.GetType("RoR2.LocalUserManager", throwOnError: false);
				if (type6 == null)
				{
					return Fail("RoR2.LocalUserManager type missing.");
				}
				if ((MemberInfo?)(((object)type6.GetProperty("readOnlyLocalUsersList", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type6.GetField("readOnlyLocalUsersList", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))) == null)
				{
					return Fail("RoR2.LocalUserManager.readOnlyLocalUsersList shape missing; personal visibility cannot safely resolve local identity.");
				}
				MethodInfo methodInfo2 = FindDisconnectMethod(assembly3);
				if (methodInfo2 == null)
				{
					return Fail("No supported network-destroy observation callback shape was found (NetworkUser/PlayerCharacterMasterController OnNetworkDestroy). DisconnectCleanup must fail closed.");
				}
				log.LogInfo((object)("[ItemShareFix] compatibility guard PASS: exact ItemShare 1.7.1 + PickupShareApi 1.0.0 / API 1 + Command picker shapes; disconnect candidate hook=" + methodInfo2.DeclaringType?.FullName + "." + methodInfo2.Name));
				return new CompatibilityResult
				{
					Supported = true,
					Reason = "Exact baseline and private shapes verified.",
					ItemShareAssembly = assembly,
					PickupShareApiAssembly = assembly2,
					DisconnectMethod = methodInfo2
				};
			}
			catch (Exception ex)
			{
				return Fail("Compatibility probe exception: " + ex);
			}
		}

		private static bool HasExactOriginalDelegateHookShape(MethodInfo hookMethod, Type selfType, Type payloadType)
		{
			ParameterInfo[] parameters = hookMethod.GetParameters();
			if (parameters.Length != 3 || parameters[1].ParameterType != selfType || parameters[2].ParameterType != payloadType)
			{
				return false;
			}
			Type parameterType = parameters[0].ParameterType;
			if (!typeof(Delegate).IsAssignableFrom(parameterType))
			{
				return false;
			}
			MethodInfo method = parameterType.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public);
			if (method == null || method.ReturnType != typeof(void))
			{
				return false;
			}
			ParameterInfo[] parameters2 = method.GetParameters();
			if (parameters2.Length == 2 && parameters2[0].ParameterType == selfType)
			{
				return parameters2[1].ParameterType == payloadType;
			}
			return false;
		}

		private static bool HasStableNetworkUserIdShape(Assembly ror2Assembly, out string reason)
		{
			reason = string.Empty;
			Type type = ror2Assembly.GetType("RoR2.NetworkUser", throwOnError: false);
			Type type2 = ror2Assembly.GetType("RoR2.NetworkUserId", throwOnError: false);
			Type platformIdType = ror2Assembly.GetType("RoR2.PlatformID", throwOnError: false);
			if (type == null || type2 == null || platformIdType == null)
			{
				reason = "NetworkUser/NetworkUserId/PlatformID type missing";
				return false;
			}
			PropertyInfo property = type.GetProperty("id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field = type.GetField("id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (((property != null) ? property.PropertyType : field?.FieldType) != type2)
			{
				reason = "NetworkUser.id is missing or not RoR2.NetworkUserId";
				return false;
			}
			if ((from x in type2.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where (x is FieldInfo fieldInfo && fieldInfo.FieldType == platformIdType) || (x is PropertyInfo propertyInfo && propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.PropertyType == platformIdType)
				select x).ToArray().Length == 0)
			{
				reason = "NetworkUserId has no PlatformID member";
				return false;
			}
			if ((from x in type2.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where (x is FieldInfo fieldInfo && fieldInfo.FieldType == typeof(byte)) || (x is PropertyInfo propertyInfo && propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.PropertyType == typeof(byte))
				select x).ToArray().Length == 0)
			{
				reason = "NetworkUserId has no byte player-controller slot member";
				return false;
			}
			PropertyInfo? property2 = platformIdType.GetProperty("value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field2 = platformIdType.GetField("value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property2 == null && field2 == null)
			{
				reason = "PlatformID.value missing";
				return false;
			}
			return true;
		}

		private static MethodInfo? FindDisconnectMethod(Assembly ror2Assembly)
		{
			string[] array = new string[2] { "RoR2.NetworkUser", "RoR2.PlayerCharacterMasterController" };
			foreach (string name in array)
			{
				MethodInfo methodInfo = ror2Assembly.GetType(name, throwOnError: false)?.GetMethod("OnNetworkDestroy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo != null && methodInfo.GetParameters().Length == 0)
				{
					return methodInfo;
				}
			}
			return null;
		}

		private static string HashAssembly(Assembly assembly)
		{
			string location = assembly.Location;
			if (string.IsNullOrEmpty(location) || !File.Exists(location))
			{
				throw new InvalidOperationException("Assembly has no hashable on-disk location: " + assembly.FullName);
			}
			using FileStream inputStream = File.OpenRead(location);
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", string.Empty);
		}

		private static CompatibilityResult Fail(string reason)
		{
			return new CompatibilityResult
			{
				Supported = false,
				Reason = reason
			};
		}
	}
	[BepInPlugin("com.itemsharefix", "ItemShareFix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class ItemShareFixPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.itemsharefix";

		public const string PluginName = "ItemShareFix";

		public const string PluginVersion = "1.0.0";

		private Harmony? _harmony;

		private PluginConfig? _config;

		private ServerCoordinator? _server;

		private ClientPresentationCoordinator? _presentation;

		private bool _active;

		private int _riskOfOptionsLocalizationWarmupFrames;

		private void Awake()
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			_config = new PluginConfig(((BaseUnityPlugin)this).Config);
			if (!_config.Enabled.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[ItemShareFix] disabled by configuration.");
				return;
			}
			CompatibilityResult compatibilityResult = CompatibilityGuard.Probe(((BaseUnityPlugin)this).Logger);
			if (!compatibilityResult.Supported)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[ItemShareFix] FAIL-CLOSED: " + compatibilityResult.Reason));
				((Behaviour)this).enabled = false;
				return;
			}
			try
			{
				if (RemoteOperationProbe.TryVerifyRuntimeShape(out string evidence))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[ItemShareFix] Remote Operation runtime shape PASS: " + evidence));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[ItemShareFix] Remote Operation runtime shape unavailable; Support Drone classification will fail closed: " + evidence));
				}
				UpstreamBridge upstream = new UpstreamBridge(compatibilityResult.ItemShareAssembly, compatibilityResult.PickupShareApiAssembly, ((BaseUnityPlugin)this).Logger);
				_server = new ServerCoordinator(_config, upstream, ((BaseUnityPlugin)this).Logger);
				_presentation = new ClientPresentationCoordinator(_config, upstream, ((BaseUnityPlugin)this).Logger);
				_harmony = new Harmony("com.itemsharefix");
				RuntimePatches.Install(_harmony, compatibilityResult, _server, _presentation);
				_active = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[ItemShareFix] world-space marker clustering active: adaptive LOD, Detailed default / Compact optional presentation, HUD/modal suppression enabled. Gameplay/share ownership remains unchanged.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[ItemShareFix] initialization failed closed: " + ex));
				try
				{
					Harmony? harmony = _harmony;
					if (harmony != null)
					{
						harmony.UnpatchSelf();
					}
				}
				catch
				{
				}
				_presentation?.RestoreAll();
				_active = false;
				((Behaviour)this).enabled = false;
			}
		}

		private void FixedUpdate()
		{
			if (_active && _config != null)
			{
				if (!_config.Enabled.Value)
				{
					_presentation?.RestoreAll();
					return;
				}
				_server?.Tick();
				_presentation?.Tick();
			}
		}

		private void Update()
		{
			if (_config != null)
			{
				if (_riskOfOptionsLocalizationWarmupFrames < 3)
				{
					_riskOfOptionsLocalizationWarmupFrames++;
				}
				if (_riskOfOptionsLocalizationWarmupFrames >= 3)
				{
					OptionalRiskOfOptionsIntegration.TryRegister(_config, ((BaseUnityPlugin)this).Logger);
					OptionalRiskOfOptionsIntegration.TryRefreshLocalization(((BaseUnityPlugin)this).Logger);
				}
			}
			if (_active && _presentation != null)
			{
				_presentation.RecordUnityUpdate();
				_presentation.RenderFrame();
			}
		}

		private void OnDestroy()
		{
			_active = false;
			try
			{
				_presentation?.Dispose();
			}
			catch
			{
			}
			try
			{
				Harmony? harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}
	}
	internal sealed class LocalHudPresentationProbe
	{
		private sealed class MessageHudCandidate
		{
			public RectTransform Root { get; }

			public TMP_Text[] Texts { get; }

			public Selectable[] Selectables { get; }

			public Vector3[] Corners { get; } = (Vector3[])(object)new Vector3[4];

			public MessageHudCandidate(RectTransform root)
			{
				Root = root;
				Texts = ((Component)root).GetComponentsInChildren<TMP_Text>(true);
				Selectables = ((Component)root).GetComponentsInChildren<Selectable>(true);
			}
		}

		internal static readonly string[] BlockingModalTypeNames = new string[3] { "RoR2.UI.PauseScreenController", "RoR2.UI.SimpleDialogBox", "RoR2.UI.PickupPickerPanel" };

		private static readonly string[] MessageHudTypeNames = new string[3] { "RoR2.UI.ChatBox", "RoR2.UI.ChatBoxController", "RoR2.UI.HUDChat" };

		private readonly Type[] _blockingModalTypes;

		private readonly Type[] _messageHudTypes;

		private readonly Type? _hudType;

		private readonly MarkerRuntimePerformanceCounters _performance;

		private readonly List<Component> _blockingModalComponents = new List<Component>();

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

		private readonly List<MessageHudCandidate> _messageHudRoots = new List<MessageHudCandidate>();

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

		private float _nextBlockingDiscovery;

		private float _nextMessageDiscovery;

		private bool _blockingLifecycleInvalidated = true;

		private bool _messageLifecycleInvalidated = true;

		private bool _lastPauseSignal;

		public LocalHudPresentationProbe(MarkerRuntimePerformanceCounters performance)
		{
			_performance = performance ?? throw new ArgumentNullException("performance");
			Assembly assembly = typeof(Run).Assembly;
			_blockingModalTypes = ResolveComponentTypes(assembly, BlockingModalTypeNames);
			_messageHudTypes = ResolveComponentTypes(assembly, MessageHudTypeNames);
			Type type