Decompiled source of Madys HideNSeek v1.1.0

BepInEx/plugins/Madys_HideNSeek.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LobbyNetworking;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Madys_HideNSeek")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+69a7b35984bf4cc1338a873e64ae3951889c3734")]
[assembly: AssemblyProduct("Madys_HideNSeek")]
[assembly: AssemblyTitle("Madys_HideNSeek")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MadysHideNSeek
{
	public sealed class HideAndSeekTester : MonoBehaviour
	{
		private sealed class PlayArea
		{
			public readonly List<Vector3> SpawnPoints = new List<Vector3>();

			public readonly List<Vector3> Border = new List<Vector3>();

			public readonly List<Vector3> RecoveryPoints = new List<Vector3>();

			public Vector3 Center;

			public Vector3 StatusSignPosition;

			public float StatusSignYaw;

			public bool HasStatusSign;

			public bool EnforcementLights = true;
		}

		private sealed class PlayAreaSave
		{
			public string Center { get; set; } = "";

			public string Spawns { get; set; } = "";

			public string Border { get; set; } = "";

			public string Recoveries { get; set; } = "";

			public string StatusSign { get; set; } = "";

			public bool EnforcementLights { get; set; } = true;
		}

		private sealed class ItemStorageJob
		{
			public Prop Prop;

			public PlayerCharacter Worker;

			public PlayerCharacter OriginalHolder;

			public int Attempts;

			public bool NeedsSnatch;

			public bool Stored;

			public float NextAttempt;

			public float NextLog;
		}

		internal sealed class PickupSnapshot
		{
			public Prop Prop;

			public bool Blocked = true;

			public string AssignmentOwner;
		}

		private enum Phase
		{
			Idle,
			SettingUp,
			Hiding,
			Seeking,
			Ended
		}

		private readonly struct PropOrigin
		{
			public readonly Vector3 Position;

			public readonly Quaternion Rotation;

			public readonly bool Gravity;

			public readonly bool Kinematic;

			public PropOrigin(Prop p)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				Position = ((Component)p).transform.position;
				Rotation = ((Component)p).transform.rotation;
				Gravity = (Object)(object)p.rb != (Object)null && p.rb.useGravity;
				Kinematic = (Object)(object)p.rb != (Object)null && p.rb.isKinematic;
			}
		}

		private sealed class TransportRequest
		{
			public PlayerCharacter Player;

			public PlayerCharacter Worker;

			public Vector3 Target;

			public string Reason;

			public float Deadline;

			public float NextStage;

			public float StableSince;

			public int Attempts;

			public int Confirmations;

			public int Stage;

			public int LoggedStage = int.MinValue;

			public bool BorderReturn;

			public bool AirFallbackUsed;
		}

		private sealed class ClientTransportRequest
		{
			public PlayerCharacter Player;

			public Vector3 Target;

			public string Reason;

			public float NextSend;

			public int Token;

			public int Attempts;

			public bool BorderReturn;

			public bool Acknowledged;
		}

		private sealed class RemoteClientTransport
		{
			public Vector3 Target;

			public float Deadline;

			public float NextAttempt;

			public int Token;

			public int Confirmations;

			public bool BorderReturn;
		}

		private readonly List<PlayArea> playAreas = new List<PlayArea>();

		private readonly List<GameObject> debugBorderBeams = new List<GameObject>();

		private Material debugBeamMaterial;

		private float nextDebugBeamUpdate;

		private int debugBeamCursor;

		private int activeAreaIndex = -1;

		private int editingAreaIndex = -1;

		private Vector3 draftStatusSignPosition;

		private float draftStatusSignYaw;

		private bool hasDraftStatusSign;

		private bool draftEnforcementLights = true;

		private readonly HashSet<string> itemRolls = new HashSet<string>();

		private float lastItemChance = float.NaN;

		private readonly Dictionary<string, float> nextAuditLog = new Dictionary<string, float>();

		private readonly Dictionary<Prop, ItemStorageJob> itemStorageJobs = new Dictionary<Prop, ItemStorageJob>(NativeIdentity<Prop>.Instance);

		private bool finalThirtyPending;

		private float nextStorageCompletion;

		private readonly List<Behaviour> fairPlayBehaviours = new List<Behaviour>();

		private FieldInfo nameTagsVisibleField;

		private bool nameTagsWereVisible;

		private FieldInfo moderationNameTagsField;

		private bool moderationNameTagsWereVisible;

		private bool fairPlayApplied;

		private static readonly MethodInfo UseHeldUpServer = AccessTools.Method(typeof(PlayerNetworking), "UserCode_CmdUseHeldUp__PeckContext", (Type[])null, (Type[])null);

		private static readonly MethodInfo ReleaseHeldSwitchServer = AccessTools.Method(typeof(PlayerNetworking), "UserCode_CmdReleaseHeldSwitch__ShellReference__PeckContext__Int32", (Type[])null, (Type[])null);

		private readonly List<Prop> megaphones = new List<Prop>();

		private readonly List<Prop> walkies = new List<Prop>();

		private readonly List<Prop> flares = new List<Prop>();

		private readonly List<Prop> xrayGoggles = new List<Prop>();

		private readonly List<Prop> speakers = new List<Prop>();

		private readonly List<Prop> belts = new List<Prop>();

		private readonly List<Prop> bells = new List<Prop>();

		private readonly List<Prop> brushes = new List<Prop>();

		private readonly List<Prop> buoys = new List<Prop>();

		private readonly List<Prop> instructionSignProps = new List<Prop>();

		private readonly List<Prop> roundItemPool = new List<Prop>();

		private readonly Dictionary<Prop, PropOrigin> propOrigins = new Dictionary<Prop, PropOrigin>(NativeIdentity<Prop>.Instance);

		private readonly Dictionary<Prop, Vector3> markerPositions = new Dictionary<Prop, Vector3>(NativeIdentity<Prop>.Instance);

		private readonly Dictionary<Prop, Quaternion> markerRotations = new Dictionary<Prop, Quaternion>(NativeIdentity<Prop>.Instance);

		private readonly Dictionary<Prop, PropOrigin> whiteboardOrigins = new Dictionary<Prop, PropOrigin>(NativeIdentity<Prop>.Instance);

		private readonly Dictionary<Prop, int> borderDriftChecks = new Dictionary<Prop, int>(NativeIdentity<Prop>.Instance);

		private readonly Dictionary<string, List<Prop>> warningBuoys = new Dictionary<string, List<Prop>>();

		private readonly Dictionary<string, NetworkConnection> moddedClients = new Dictionary<string, NetworkConnection>();

		private readonly Dictionary<string, ClientTransportRequest> clientTransports = new Dictionary<string, ClientTransportRequest>();

		private readonly HashSet<NetworkConnection> failedModConnections = new HashSet<NetworkConnection>();

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

		private readonly Queue<TransportRequest> priorityTransports = new Queue<TransportRequest>();

		private readonly Queue<TransportRequest> transports = new Queue<TransportRequest>();

		private readonly HashSet<string> seekers = new HashSet<string>();

		private readonly HashSet<string> hiders = new HashSet<string>();

		private readonly HashSet<string> caught = new HashSet<string>();

		private readonly HashSet<string> known = new HashSet<string>();

		private readonly HashSet<string> disconnected = new HashSet<string>();

		private readonly HashSet<string> setupConfirmed = new HashSet<string>();

		private readonly HashSet<string> deployingSeekers = new HashSet<string>();

		private bool seekerDeployment;

		private readonly HashSet<string> setupItemsGiven = new HashSet<string>();

		private readonly HashSet<PlayerCharacter> goldApplied = new HashSet<PlayerCharacter>();

		private readonly Dictionary<string, float> borderCooldown = new Dictionary<string, float>();

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

		private readonly Dictionary<string, float> disconnectDeadlines = new Dictionary<string, float>();

		private readonly Dictionary<string, Vector3> roundSpawnPositions = new Dictionary<string, Vector3>();

		private readonly Dictionary<List<Vector3>, Dictionary<string, int>> spawnReservations = new Dictionary<List<Vector3>, Dictionary<string, int>>();

		private readonly Dictionary<PlayerCharacter, float> fallProtectionUntil = new Dictionary<PlayerCharacter, float>();

		private readonly Dictionary<string, PlayerCharacter> roundPlayers = new Dictionary<string, PlayerCharacter>();

		private readonly Dictionary<string, Corpse> trackedCorpses = new Dictionary<string, Corpse>();

		private readonly Dictionary<string, Vector3> corpseTargets = new Dictionary<string, Vector3>();

		private List<Vector3> corpsePlacementCandidates;

		private readonly Dictionary<string, Prop> normalItemAssignments = new Dictionary<string, Prop>();

		private readonly Dictionary<string, Prop> lockedSpeakerAssignments = new Dictionary<string, Prop>();

		private readonly Dictionary<string, Prop> seekerBeltAssignments = new Dictionary<string, Prop>();

		private readonly Dictionary<string, Prop> seekerBellAssignments = new Dictionary<string, Prop>();

		private readonly List<TransportRequest> activeTransports = new List<TransportRequest>();

		private readonly List<GameObject> permanentDummyObjects = new List<GameObject>();

		private readonly List<PlayerCharacter> dummyManagers = new List<PlayerCharacter>();

		private readonly List<PlayerCharacter> standbyManagers = new List<PlayerCharacter>();

		private readonly List<Vector3> hiderSpawnSlots = new List<Vector3>();

		private readonly List<Vector3> seekerSpawnSlots = new List<Vector3>();

		private readonly List<Vector3> endSpawnSlots = new List<Vector3>();

		private readonly List<Vector3> standbySlots = new List<Vector3>();

		private readonly List<Vector3> spawnPoints = new List<Vector3>();

		private readonly List<Vector3> borderPoints = new List<Vector3>();

		private readonly List<Vector3> playBorder = new List<Vector3>();

		private readonly List<Vector3> seekerBorder = new List<Vector3>();

		private readonly List<Vector3> endBorder = new List<Vector3>();

		private readonly List<Vector3> recoveryPoints = new List<Vector3>();

		private readonly List<Vector3> playRecoveryPoints = new List<Vector3>();

		private readonly List<Vector3> instructionSignPositions = new List<Vector3>();

		private readonly List<float> instructionSignYaws = new List<float>();

		private readonly List<PeckEffectTextInput> instructionSignBoards = new List<PeckEffectTextInput>();

		private readonly Dictionary<uint, string> expectedSignText = new Dictionary<uint, string>();

		private bool simpleVisible;

		private bool setupVisible;

		private bool poolBuilt;

		private bool enforceBorder = true;

		private bool cleanupPending;

		private bool showSpawnDebug;

		private bool spawnDraftLights;

		private bool finalThirtyTriggered;

		private bool menuCursorActive;

		private bool previousCursorVisible;

		private readonly Dictionary<PlayerCharacter, Prop> cleanupManagerItems = new Dictionary<PlayerCharacter, Prop>(NativeIdentity<PlayerCharacter>.Instance);

		private readonly Dictionary<Prop, float> brushPickupGraceUntil = new Dictionary<Prop, float>(NativeIdentity<Prop>.Instance);

		private CursorLockMode previousCursorLock;

		private Rect simpleWindow = new Rect(25f, 55f, 500f, 560f);

		private Rect setupWindow = new Rect(540f, 55f, 650f, 760f);

		private Vector2 simpleScroll;

		private Vector2 setupScroll;

		private Vector3 center;

		private Vector3 seekerSpawn;

		private Vector3 endSpawn;

		private Vector3 gearStorage;

		private Vector3 seekerSignPosition;

		private Vector3 endSignPosition;

		private Vector3 statusSignPosition;

		private float seekerSignYaw;

		private float endSignYaw;

		private float statusSignYaw;

		private bool hasCenter;

		private bool hasSeeker;

		private bool hasEndSpawn;

		private bool hasGearStorage;

		private bool hasSeekerSign;

		private bool hasEndSign;

		private bool hasStatusSign;

		private Phase phase;

		private float remaining;

		private float nextTick;

		private float nextScan;

		private float nextCapture;

		private float nextTimeApply;

		private float nextMarkerPin;

		private float nextDummyCorpseCleanup;

		private float nextModNetworkCheck;

		private float nextSettingsSync;

		private int dummySerial;

		private int clientTransportSerial;

		private bool modHelloSent;

		private bool serverModHandlerInstalled;

		private bool clientModHandlerInstalled;

		private bool modLinkDisabled;

		private NetworkMessageDelegate serverModHandler;

		private NetworkMessageDelegate clientModHandler;

		private const ushort ModMessageId = 59297;

		private const string ModProtocol = "2";

		private float nextModHello;

		private int completedRemoteToken;

		private int cancelledRemoteToken;

		private string syncedHostSettings = "";

		private string lastSettingsPacket = "";

		private RemoteClientTransport remoteClientTransport;

		private string status = "Save positions, build pool once, start round.";

		private Prop seekerBoardProp;

		private Prop endBoardProp;

		private Prop statusBoardProp;

		private PeckEffectTextInput seekerBoard;

		private PeckEffectTextInput endBoard;

		private PeckEffectTextInput statusBoard;

		internal static HideAndSeekTester Instance;

		internal static bool CreatingDummyManager;

		private bool sessionEnabled;

		private bool remoteSessionEnabled;

		private PlayerCharacter sessionLocal;

		private bool sessionWasServer;

		private string presetName = "My preset";

		private string loadedPresetName = "";

		private string setupBaseline = "";

		private string[] savedPresets = Array.Empty<string>();

		private static string PresetDirectory => Path.Combine(Paths.ConfigPath, "MadysHideNSeekPresets");

		private static string LegacyMapDirectory => Path.Combine(Paths.ConfigPath, "HideAndSeekMaps");

		internal static bool ActiveHost
		{
			get
			{
				if ((Object)(object)Instance != (Object)null && Instance.sessionEnabled)
				{
					return NetworkServer.active;
				}
				return false;
			}
		}

		public static bool SuppressMinimapPlayerBlips
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					if (!Instance.sessionEnabled)
					{
						return Instance.remoteSessionEnabled;
					}
					return true;
				}
				return false;
			}
		}

		public static bool SuppressMinimap => SuppressMinimapPlayerBlips;

		private void LoadPlayAreas()
		{
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			playAreas.Clear();
			bool flag = false;
			try
			{
				if (!string.IsNullOrWhiteSpace(Plugin.PlayAreas.Value))
				{
					List<PlayAreaSave> list = JsonSerializer.Deserialize<List<PlayAreaSave>>(Plugin.PlayAreas.Value);
					if (list != null)
					{
						foreach (PlayAreaSave item in list)
						{
							PlayArea playArea = new PlayArea();
							if (TryVector(item.Center, out playArea.Center))
							{
								LoadSlots(item.Spawns, playArea.SpawnPoints, 11);
								LoadSlots(item.Border, playArea.Border, 20);
								LoadSlots(item.Recoveries, playArea.RecoveryPoints, int.MaxValue);
								playArea.HasStatusSign = TrySign(item.StatusSign, out playArea.StatusSignPosition, out playArea.StatusSignYaw);
								playArea.EnforcementLights = item.EnforcementLights;
								if (!playArea.HasStatusSign && hasStatusSign)
								{
									playArea.HasStatusSign = true;
									playArea.StatusSignPosition = statusSignPosition;
									playArea.StatusSignYaw = statusSignYaw;
									flag = true;
								}
								if (playArea.SpawnPoints.Count == 11 && playArea.Border.Count >= 4 && playArea.RecoveryPoints.Count > 0)
								{
									playAreas.Add(playArea);
								}
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("[AREAS] Saved area data invalid: " + ex.Message));
			}
			if (playAreas.Count == 0 && hasCenter && hiderSpawnSlots.Count == 11 && playBorder.Count >= 4 && playRecoveryPoints.Count > 0)
			{
				PlayArea playArea2 = new PlayArea
				{
					Center = center,
					HasStatusSign = hasStatusSign,
					StatusSignPosition = statusSignPosition,
					StatusSignYaw = statusSignYaw
				};
				playArea2.SpawnPoints.AddRange(hiderSpawnSlots);
				playArea2.Border.AddRange(playBorder);
				playArea2.RecoveryPoints.AddRange(playRecoveryPoints);
				playAreas.Add(playArea2);
				SavePlayAreas();
				Plugin.Logger.LogInfo((object)"[AREAS] Migrated legacy play area to area 1.");
			}
			Plugin.AreaSelection.Value = Mathf.Clamp(Plugin.AreaSelection.Value, 0, playAreas.Count);
			if (flag)
			{
				SavePlayAreas();
			}
		}

		private void SavePlayAreas()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			List<PlayAreaSave> list = new List<PlayAreaSave>();
			foreach (PlayArea playArea in playAreas)
			{
				list.Add(new PlayAreaSave
				{
					Center = FormatVector(playArea.Center),
					Spawns = FormatSlots(playArea.SpawnPoints),
					Border = FormatSlots(playArea.Border),
					Recoveries = FormatSlots(playArea.RecoveryPoints),
					StatusSign = (playArea.HasStatusSign ? FormatSign(playArea.StatusSignPosition, playArea.StatusSignYaw) : ""),
					EnforcementLights = playArea.EnforcementLights
				});
			}
			Plugin.PlayAreas.Value = JsonSerializer.Serialize(list);
		}

		private void SaveNewPlayArea()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (spawnPoints.Count != 11 || borderPoints.Count < 4 || recoveryPoints.Count == 0 || !hasDraftStatusSign)
			{
				status = "Area needs 11 Spawn points, at least 4 Border points, at least 1 Recover point, and its play sign.";
				return;
			}
			PlayArea playArea = new PlayArea
			{
				Center = spawnPoints[0],
				HasStatusSign = true,
				StatusSignPosition = draftStatusSignPosition,
				StatusSignYaw = draftStatusSignYaw,
				EnforcementLights = draftEnforcementLights
			};
			playArea.SpawnPoints.AddRange(spawnPoints);
			playArea.Border.AddRange(borderPoints);
			playArea.RecoveryPoints.AddRange(recoveryPoints);
			if (editingAreaIndex >= 0 && editingAreaIndex < playAreas.Count)
			{
				playAreas[editingAreaIndex] = playArea;
			}
			else
			{
				playAreas.Add(playArea);
			}
			int value = ((editingAreaIndex >= 0) ? (editingAreaIndex + 1) : playAreas.Count);
			editingAreaIndex = -1;
			SavePlayAreas();
			spawnPoints.Clear();
			borderPoints.Clear();
			recoveryPoints.Clear();
			hasDraftStatusSign = false;
			Plugin.DraftSpawnSlots.Value = "";
			Plugin.BorderPoints.Value = "";
			Plugin.DraftRecoveryPoints.Value = "";
			spawnDraftLights = false;
			PositionMarkers();
			status = $"Area {value} saved. Draft reset to Spawn 1, Border 1, Recover 1.";
		}

		private void ClearAreaDraft()
		{
			spawnPoints.Clear();
			borderPoints.Clear();
			recoveryPoints.Clear();
			hasDraftStatusSign = false;
			editingAreaIndex = -1;
			draftEnforcementLights = true;
			Plugin.DraftSpawnSlots.Value = "";
			Plugin.BorderPoints.Value = "";
			Plugin.DraftRecoveryPoints.Value = "";
			spawnDraftLights = false;
			if (poolBuilt)
			{
				PositionMarkers();
			}
			showSpawnDebug = true;
			status = "Area draft cancelled.";
		}

		private void EditSelectedPlayArea()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			int value = Plugin.AreaSelection.Value;
			if (value <= 0 || value > playAreas.Count)
			{
				status = "Select a specific play area first.";
				return;
			}
			PlayArea playArea = playAreas[value - 1];
			editingAreaIndex = value - 1;
			spawnPoints.Clear();
			spawnPoints.AddRange(playArea.SpawnPoints);
			borderPoints.Clear();
			borderPoints.AddRange(playArea.Border);
			recoveryPoints.Clear();
			recoveryPoints.AddRange(playArea.RecoveryPoints);
			hasDraftStatusSign = playArea.HasStatusSign;
			draftStatusSignPosition = playArea.StatusSignPosition;
			draftStatusSignYaw = playArea.StatusSignYaw;
			draftEnforcementLights = playArea.EnforcementLights;
			Plugin.DraftSpawnSlots.Value = FormatSlots(spawnPoints);
			Plugin.BorderPoints.Value = FormatSlots(borderPoints);
			Plugin.DraftRecoveryPoints.Value = FormatSlots(recoveryPoints);
			showSpawnDebug = true;
			spawnDraftLights = false;
			status = $"Editing area {value}. Right-click Spawn, Border, or Recover to undo points, then save.";
		}

		private void DeleteSelectedPlayArea()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			if (phase != Phase.Idle && phase != Phase.Ended)
			{
				status = "Finish round before deleting areas.";
				return;
			}
			int value = Plugin.AreaSelection.Value;
			if (value <= 0 || value > playAreas.Count)
			{
				status = "Select a specific play area first.";
				return;
			}
			if (activeAreaIndex == value - 1)
			{
				activeAreaIndex = -1;
			}
			else if (activeAreaIndex > value - 1)
			{
				activeAreaIndex--;
			}
			playAreas.RemoveAt(value - 1);
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(35, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[AREA DELETE] deleted=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" activeIndex=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(activeAreaIndex);
			}
			logger.LogInfo(val);
			SavePlayAreas();
			Plugin.AreaSelection.Value = Mathf.Clamp(value - 1, 0, playAreas.Count);
			editingAreaIndex = -1;
			status = $"Deleted area {value}.";
		}

		private void DrawAreaEditControls()
		{
			int value = Plugin.AreaSelection.Value;
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUI.enabled = value > 0 && value <= playAreas.Count;
			if (GUILayout.Button("Edit Selected Area", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				EditSelectedPlayArea();
			}
			if (GUILayout.Button("Delete Selected Area", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				DeleteSelectedPlayArea();
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			if (editingAreaIndex < 0 && spawnPoints.Count == 0 && borderPoints.Count == 0 && recoveryPoints.Count == 0 && value > 0 && value <= playAreas.Count)
			{
				bool flag = GUILayout.Toggle(playAreas[value - 1].EnforcementLights, $"Area {value} enforcement warning lights", Array.Empty<GUILayoutOption>());
				if (flag != playAreas[value - 1].EnforcementLights)
				{
					playAreas[value - 1].EnforcementLights = flag;
					SavePlayAreas();
				}
			}
			else
			{
				draftEnforcementLights = GUILayout.Toggle(draftEnforcementLights, "Use enforcement warning lights in this area", Array.Empty<GUILayoutOption>());
			}
		}

		private bool ActivateSelectedPlayArea()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			if (playAreas.Count == 0)
			{
				status = "Create at least one play area in F10.";
				return false;
			}
			int num = Mathf.Clamp(Plugin.AreaSelection.Value, 0, playAreas.Count);
			activeAreaIndex = ((num == 0) ? Random.Range(0, playAreas.Count) : (num - 1));
			PlayArea playArea = playAreas[activeAreaIndex];
			spawnDraftLights = false;
			center = playArea.Center;
			hasCenter = true;
			hiderSpawnSlots.Clear();
			hiderSpawnSlots.AddRange(playArea.SpawnPoints);
			playBorder.Clear();
			playBorder.AddRange(playArea.Border);
			playRecoveryPoints.Clear();
			playRecoveryPoints.AddRange(playArea.RecoveryPoints);
			hasStatusSign = playArea.HasStatusSign;
			statusSignPosition = playArea.StatusSignPosition;
			statusSignYaw = playArea.StatusSignYaw;
			Plugin.AreaPoint.Value = FormatVector(center);
			Plugin.HiderSpawnSlots.Value = FormatSlots(hiderSpawnSlots);
			Plugin.PlayBorder.Value = FormatSlots(playBorder);
			Plugin.PlayRecoveryPoints.Value = FormatSlots(playRecoveryPoints);
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[AREAS] Round selected area ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(activeAreaIndex + 1);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(playAreas.Count);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
			}
			logger.LogInfo(val);
			return true;
		}

		private void DrawAreaSelector()
		{
			int num = Mathf.Clamp(Plugin.AreaSelection.Value, 0, playAreas.Count);
			Plugin.AreaSelection.Value = num;
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label((num == 0) ? $"Play area: Random (1-{playAreas.Count})" : $"Play area: {num} of {playAreas.Count}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) });
			if (GUILayout.Button("<", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(38f) }))
			{
				Plugin.AreaSelection.Value = ((num <= 0) ? playAreas.Count : (num - 1));
			}
			if (GUILayout.Button(">", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(38f) }))
			{
				Plugin.AreaSelection.Value = ((num < playAreas.Count) ? (num + 1) : 0);
			}
			GUILayout.EndHorizontal();
		}

		private void DrawItemCategoryControls()
		{
			GUILayout.Label("Random hider item categories", (Il2CppReferenceArray<GUILayoutOption>)null);
			DrawItemCategory("Megaphones", Plugin.EnableMegaphones, Plugin.MegaphoneItemCount, AvailableItemCount("MegaphoneProp"));
			DrawItemCategory("Flares", Plugin.EnableFlares, Plugin.FlareItemCount, AvailableItemCount("FlareGunProp"));
			DrawItemCategory("Goggles", Plugin.EnableGoggles, Plugin.GogglesItemCount, AvailableItemCount("XrayGogglesProp"));
			DrawItemCategory("Speakers", Plugin.EnableSpeakers, Plugin.SpeakerItemCount, Mathf.Min(10, AvailableItemCount("PegTileProp Speaker")));
		}

		private void DrawItemCategory(string label, ConfigEntry<bool> enabled, ConfigEntry<int> count, int maximum)
		{
			maximum = Mathf.Max(0, maximum);
			if (count.Value > maximum)
			{
				count.Value = maximum;
			}
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			enabled.Value = GUILayout.Toggle(enabled.Value, label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			GUI.enabled = enabled.Value;
			LiveInt("Amount", count, 0, maximum);
			GUI.enabled = true;
			GUILayout.EndHorizontal();
		}

		private static int AvailableItemCount(string prefix)
		{
			int num = 0;
			if (Prop.allProps != null)
			{
				Enumerator<Prop> enumerator = Prop.allProps.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Prop current = enumerator.Current;
					if ((Object)(object)current != (Object)null && ((Object)current).name.StartsWith(prefix, StringComparison.Ordinal))
					{
						num++;
					}
				}
			}
			return num;
		}

		private static bool RightClickedLastControl()
		{
			//IL_0013: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Event current = Event.current;
			if (current != null && current.button == 1 && ((int)current.type == 0 || (int)current.rawType == 0))
			{
				Rect lastRect = GUILayoutUtility.GetLastRect();
				if (((Rect)(ref lastRect)).Contains(current.mousePosition))
				{
					current.Use();
					return true;
				}
			}
			return false;
		}

		private static bool DraftButton(string label, out bool rightClicked)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(0f, 10000f, 24f, 24f);
			Event current = Event.current;
			rightClicked = current != null && current.button == 1 && ((int)current.type == 0 || (int)current.rawType == 0) && ((Rect)(ref rect)).Contains(current.mousePosition);
			if (rightClicked)
			{
				current.Use();
			}
			return GUI.Button(rect, label);
		}

		private string AreaSignButtonLabel()
		{
			int value = Plugin.AreaSelection.Value;
			if (spawnPoints.Count != 0 || borderPoints.Count != 0 || recoveryPoints.Count != 0 || value <= 0 || value > playAreas.Count)
			{
				if (!hasDraftStatusSign)
				{
					return "Set Area Play Sign Draft";
				}
				return "Area play sign draft: Set";
			}
			return $"Set Area {value} Play Sign";
		}

		private void SaveDraftStatusSign(PlayerCharacter local)
		{
			//IL_011e: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)local == (Object)null)
			{
				return;
			}
			int value = Plugin.AreaSelection.Value;
			if (spawnPoints.Count == 0 && borderPoints.Count == 0 && recoveryPoints.Count == 0 && value > 0 && value <= playAreas.Count)
			{
				PlayArea playArea = playAreas[value - 1];
				playArea.HasStatusSign = true;
				playArea.StatusSignPosition = ((Component)local).transform.position;
				playArea.StatusSignYaw = ((Component)local).transform.eulerAngles.y;
				SavePlayAreas();
				if (activeAreaIndex == value - 1)
				{
					hasStatusSign = true;
					statusSignPosition = playArea.StatusSignPosition;
					statusSignYaw = playArea.StatusSignYaw;
					if (poolBuilt)
					{
						PositionMarkers();
					}
				}
				showSpawnDebug = true;
				status = $"Area {value} play sign saved.";
			}
			else
			{
				draftStatusSignPosition = ((Component)local).transform.position;
				draftStatusSignYaw = ((Component)local).transform.eulerAngles.y;
				hasDraftStatusSign = true;
				showSpawnDebug = true;
				status = "Area play sign draft saved.";
			}
		}

		private void ClearAreaStatusSign()
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			int value = Plugin.AreaSelection.Value;
			if (spawnPoints.Count == 0 && borderPoints.Count == 0 && recoveryPoints.Count == 0 && value > 0 && value <= playAreas.Count)
			{
				playAreas[value - 1].HasStatusSign = false;
				SavePlayAreas();
				if (activeAreaIndex == value - 1)
				{
					hasStatusSign = false;
					Plugin.StatusSignTransform.Value = "";
					if ((Object)(object)statusBoardProp != (Object)null)
					{
						markerPositions.Remove(statusBoardProp);
						markerRotations.Remove(statusBoardProp);
						PlaceLoose(statusBoardProp, MarkerStorage(), Quaternion.identity);
					}
				}
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SIGN CLEAR] area=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" active=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(activeAreaIndex + 1);
				}
				logger.LogInfo(val);
				status = $"Area {value} play sign cleared.";
			}
			else
			{
				hasDraftStatusSign = false;
				status = "Area play sign draft cleared.";
			}
		}

		private void UndoPoint(List<Vector3> points, ConfigEntry<string> config, string label)
		{
			if (points.Count > 0)
			{
				points.RemoveAt(points.Count - 1);
			}
			config.Value = FormatSlots(points);
			showSpawnDebug = true;
			status = $"Undid {label}. {points.Count} left.";
		}

		private void SetShowObjects(bool show)
		{
			showSpawnDebug = show;
			status = (show ? "Showing object positions, signs, and border beams." : "Object preview hidden.");
		}

		private bool ActiveAreaUsesEnforcementLights()
		{
			if (activeAreaIndex >= 0 && activeAreaIndex < playAreas.Count)
			{
				return playAreas[activeAreaIndex].EnforcementLights;
			}
			return true;
		}

		private static Color AreaColor(int index)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Color result = Color.HSVToRGB((float)index * 0.173f % 1f, 0.8f, 1f);
			result.a = 1f;
			return result;
		}

		private void LateUpdate()
		{
			if (!showSpawnDebug)
			{
				ClearDebugBeams();
			}
			else if (!(Time.unscaledTime < nextDebugBeamUpdate))
			{
				nextDebugBeamUpdate = Time.unscaledTime + 0.25f;
				UpdateDebugBeams();
			}
		}

		private void UpdateDebugBeams()
		{
			//IL_001e: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			debugBeamCursor = 0;
			for (int i = 0; i < playAreas.Count; i++)
			{
				AddDebugBeam(playAreas[i].Border, AreaColor(i));
			}
			AddDebugBeam(seekerBorder, Color.yellow);
			AddDebugBeam(endBorder, Color.cyan);
			AddDebugBeam(borderPoints, Color.magenta);
			while (debugBorderBeams.Count > debugBeamCursor)
			{
				int index = debugBorderBeams.Count - 1;
				if ((Object)(object)debugBorderBeams[index] != (Object)null)
				{
					Object.Destroy((Object)(object)debugBorderBeams[index]);
				}
				debugBorderBeams.RemoveAt(index);
			}
		}

		private void AddDebugBeam(List<Vector3> points, Color color)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			if (points.Count < 2)
			{
				return;
			}
			LineRenderer val2;
			if (debugBeamCursor < debugBorderBeams.Count && (Object)(object)debugBorderBeams[debugBeamCursor] != (Object)null)
			{
				GameObject val = debugBorderBeams[debugBeamCursor];
				val2 = val.GetComponent<LineRenderer>();
			}
			else
			{
				GameObject val = new GameObject("HNS Setup Border Beam");
				val2 = val.AddComponent<LineRenderer>();
				if (debugBeamCursor < debugBorderBeams.Count)
				{
					debugBorderBeams[debugBeamCursor] = val;
				}
				else
				{
					debugBorderBeams.Add(val);
				}
				Plugin.Logger.LogDebug((object)"[PREVIEW] allocated reusable border beam");
			}
			debugBeamCursor++;
			val2.useWorldSpace = true;
			val2.positionCount = points.Count + 1;
			val2.startWidth = 0.05f;
			val2.endWidth = 0.05f;
			val2.startColor = color;
			val2.endColor = color;
			if ((Object)(object)debugBeamMaterial == (Object)null)
			{
				Shader val3 = Shader.Find("Sprites/Default");
				if ((Object)(object)val3 != (Object)null)
				{
					debugBeamMaterial = new Material(val3);
				}
			}
			if ((Object)(object)debugBeamMaterial != (Object)null)
			{
				((Renderer)val2).material = debugBeamMaterial;
			}
			for (int i = 0; i < points.Count; i++)
			{
				val2.SetPosition(i, points[i] + Vector3.up * 0.15f);
			}
			val2.SetPosition(points.Count, points[0] + Vector3.up * 0.15f);
		}

		private void ClearDebugBeams()
		{
			foreach (GameObject debugBorderBeam in debugBorderBeams)
			{
				if ((Object)(object)debugBorderBeam != (Object)null)
				{
					Object.Destroy((Object)(object)debugBorderBeam);
				}
			}
			debugBorderBeams.Clear();
		}

		private void AuditLog(string key, string message, bool warning = false)
		{
			if (!nextAuditLog.TryGetValue(key, out var value) || !(Time.unscaledTime < value))
			{
				nextAuditLog[key] = Time.unscaledTime + 5f;
				if (warning)
				{
					Plugin.Logger.LogWarning((object)message);
				}
				else
				{
					Plugin.Logger.LogDebug((object)message);
				}
			}
		}

		private Dictionary<string, string> DraftState()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			return new Dictionary<string, string>
			{
				{
					"draft/sign",
					hasDraftStatusSign ? FormatSign(draftStatusSignPosition, draftStatusSignYaw) : ""
				},
				{
					"draft/enforcementLights",
					draftEnforcementLights.ToString()
				},
				{
					"draft/editingArea",
					editingAreaIndex.ToString()
				}
			};
		}

		private void RestoreDraftState(Dictionary<string, string> values)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			hasDraftStatusSign = values.TryGetValue("draft/sign", out var value) && TrySign(value, out draftStatusSignPosition, out draftStatusSignYaw);
			bool result = default(bool);
			draftEnforcementLights = !values.TryGetValue("draft/enforcementLights", out var value2) || !bool.TryParse(value2, out result) || result;
			editingAreaIndex = ((values.TryGetValue("draft/editingArea", out var value3) && int.TryParse(value3, out var result2)) ? result2 : (-1));
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(42, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[DRAFT RESTORE] sign=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(hasDraftStatusSign);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" editingArea=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(editingAreaIndex + 1);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" lights=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(draftEnforcementLights);
			}
			logger.LogDebug(val);
		}

		private void AssignSeekerGear(PlayerCharacter player, string key)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			if (!seekerBeltAssignments.TryGetValue(key, out var value) || (Object)(object)value == (Object)null)
			{
				foreach (Prop belt in belts)
				{
					if ((Object)(object)belt != (Object)null && !seekerBeltAssignments.Values.ContainsProp(belt))
					{
						value = (seekerBeltAssignments[key] = belt);
						break;
					}
				}
			}
			if (!seekerBellAssignments.TryGetValue(key, out var value2) || (Object)(object)value2 == (Object)null)
			{
				foreach (Prop bell in bells)
				{
					if ((Object)(object)bell != (Object)null && !seekerBellAssignments.Values.ContainsProp(bell))
					{
						value2 = (seekerBellAssignments[key] = bell);
						break;
					}
				}
			}
			if ((Object)(object)value != (Object)null)
			{
				EquipBelt(player, value);
			}
			if ((Object)(object)value2 != (Object)null)
			{
				Stow(player, value2);
			}
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExDebugLogInterpolatedStringHandler val3 = new BepInExDebugLogInterpolatedStringHandler(38, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[GEAR RESERVATION] player=");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(key);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" belt=");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((value != null) ? ((Object)value).name : null);
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" bell=");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((value2 != null) ? ((Object)value2).name : null);
			}
			logger.LogDebug(val3);
		}

		private void QueueItemStorage(Prop prop)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			if ((Object)(object)prop == (Object)null)
			{
				return;
			}
			if (itemStorageJobs.TryGetValue(prop, out var value))
			{
				string key = "storage-duplicate:" + ((NetworkBehaviour)prop).netId;
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(58, 3);
				defaultInterpolatedStringHandler.AppendLiteral("[ITEM STORAGE] existing job reused item=");
				defaultInterpolatedStringHandler.AppendFormatted(((Object)prop).name);
				defaultInterpolatedStringHandler.AppendLiteral(" netId=");
				defaultInterpolatedStringHandler.AppendFormatted(((NetworkBehaviour)prop).netId);
				defaultInterpolatedStringHandler.AppendLiteral(" managerId=");
				PlayerCharacter worker = value.Worker;
				uint? value2;
				if (worker == null)
				{
					value2 = null;
				}
				else
				{
					PlayerNetworking playerNetworking = worker.playerNetworking;
					value2 = ((playerNetworking != null) ? new uint?(((NetworkBehaviour)playerNetworking).netId) : ((uint?)null));
				}
				defaultInterpolatedStringHandler.AppendFormatted(value2);
				AuditLog(key, defaultInterpolatedStringHandler.ToStringAndClear());
			}
			else
			{
				PlayerCharacter val = FindHolder(prop);
				itemStorageJobs[prop] = new ItemStorageJob
				{
					Prop = prop,
					OriginalHolder = val,
					NeedsSnatch = ((Object)(object)val != (Object)null || normalItemAssignments.Values.ContainsProp(prop) || lockedSpeakerAssignments.Values.ContainsProp(prop))
				};
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(29, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[ITEM STORAGE] queued ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)prop).name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" netId=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<uint>(((NetworkBehaviour)prop).netId);
				}
				logger.LogDebug(val2);
			}
		}

		private void ProcessItemStorage()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Expected O, but got Unknown
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Expected O, but got Unknown
			//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c4: Expected O, but got Unknown
			if (itemStorageJobs.Count == 0 && !cleanupPending && !finalThirtyPending)
			{
				return;
			}
			bool flag2 = default(bool);
			foreach (KeyValuePair<Prop, ItemStorageJob> item in new Dictionary<Prop, ItemStorageJob>(itemStorageJobs, NativeIdentity<Prop>.Instance))
			{
				ItemStorageJob value = item.Value;
				Prop prop = value.Prop;
				try
				{
					if ((Object)(object)prop == (Object)null)
					{
						ReleaseStorageWorker(value);
						itemStorageJobs.Remove(item.Key);
					}
					else
					{
						if (Time.unscaledTime < value.NextAttempt)
						{
							continue;
						}
						if (!Object.ReferenceEquals((Object)(object)value.Worker, (Object)null) && !CanTransportPlayer(value.Worker))
						{
							ReleaseStorageWorker(value);
							value.Attempts = 0;
							value.Stored = false;
						}
						if (!((Object)(object)value.Worker == (Object)null))
						{
							goto IL_031f;
						}
						if (!value.NeedsSnatch && (Object)(object)FindHolder(prop) == (Object)null)
						{
							PlaceLoose(prop, MarkerStorage(), Quaternion.identity);
							itemStorageJobs.Remove(prop);
							continue;
						}
						foreach (PlayerCharacter standbyManager in standbyManagers)
						{
							if (cleanupManagerItems.Count >= Mathf.Max(1, standbyManagers.Count - 1))
							{
								break;
							}
							if (!CanTransportPlayer(standbyManager) || cleanupManagerItems.ContainsKey(standbyManager) || (Object)(object)standbyManager.hands.heldCharacter != (Object)null || (Object)(object)standbyManager.hands.heldProp != (Object)null)
							{
								continue;
							}
							bool flag = false;
							foreach (TransportRequest activeTransport in activeTransports)
							{
								if ((Object)(object)activeTransport.Worker == (Object)(object)standbyManager)
								{
									flag = true;
									break;
								}
							}
							if (!flag)
							{
								value.Worker = standbyManager;
								value.Attempts = 0;
								value.Stored = false;
								cleanupManagerItems[standbyManager] = prop;
								break;
							}
						}
						if ((Object)(object)value.Worker == (Object)null)
						{
							if (Time.unscaledTime >= value.NextLog)
							{
								ManualLogSource logger = Plugin.Logger;
								BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(54, 2, ref flag2);
								if (flag2)
								{
									((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[ITEM STORAGE] waiting for free manager: ");
									((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)prop).name);
									((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; transports=");
									((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(activeTransports.Count);
								}
								logger.LogWarning(val);
								value.NextLog = Time.unscaledTime + 5f;
							}
							value.NextAttempt = Time.unscaledTime + 0.05f;
							continue;
						}
						ManualLogSource logger2 = Plugin.Logger;
						BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(46, 3, ref flag2);
						if (flag2)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[ITEM STORAGE] managerId=");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<uint>(((NetworkBehaviour)value.Worker.playerNetworking).netId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" reserved for ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)prop).name);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" netId=");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<uint>(((NetworkBehaviour)prop).netId);
						}
						logger2.LogDebug(val2);
						goto IL_031f;
					}
					goto end_IL_0050;
					IL_031f:
					if (!CanTransportPlayer(value.Worker))
					{
						ReleaseStorageWorker(value);
						value.Attempts = 0;
						continue;
					}
					PlayerHands hands = value.Worker.hands;
					PlayerCharacter val3 = (((Object)(object)((hands != null) ? hands.heldProp : null) == (Object)(object)prop) ? value.Worker : FindHolder(prop));
					if (!value.Stored && (Object)(object)val3 != (Object)(object)value.Worker)
					{
						value.Attempts++;
						value.NextAttempt = Time.unscaledTime + 0.05f;
						if ((Object)(object)val3 != (Object)null)
						{
							if ((Object)(object)value.OriginalHolder == (Object)null)
							{
								value.OriginalHolder = val3;
							}
							val3.playerNetworking.ServerDropPropFromSnatch();
							BroadcastSnapshot((NetworkBehaviour)(object)val3.playerNetworking);
						}
						value.Worker.playerNetworking.ServerPickUpPropAutomatic(prop);
						BroadcastSnapshot((NetworkBehaviour)(object)value.Worker.playerNetworking);
						if ((Object)(object)value.Worker.hands.heldProp == (Object)(object)prop)
						{
							value.NextAttempt = Time.unscaledTime + 0.5f;
						}
						string key = "storage-snatch:" + ((Object)prop).GetInstanceID();
						DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(112, 6);
						defaultInterpolatedStringHandler.AppendLiteral("[ITEM STORAGE] snatch attempt=");
						defaultInterpolatedStringHandler.AppendFormatted(value.Attempts);
						defaultInterpolatedStringHandler.AppendLiteral(" item=");
						defaultInterpolatedStringHandler.AppendFormatted(((Object)prop).name);
						defaultInterpolatedStringHandler.AppendLiteral(" netId=");
						defaultInterpolatedStringHandler.AppendFormatted(((NetworkBehaviour)prop).netId);
						defaultInterpolatedStringHandler.AppendLiteral(" managerId=");
						defaultInterpolatedStringHandler.AppendFormatted(((NetworkBehaviour)value.Worker.playerNetworking).netId);
						defaultInterpolatedStringHandler.AppendLiteral(" original=");
						PlayerCharacter originalHolder = value.OriginalHolder;
						defaultInterpolatedStringHandler.AppendFormatted((originalHolder != null) ? ((Object)originalHolder).name : null);
						defaultInterpolatedStringHandler.AppendLiteral(" managerHolds=");
						defaultInterpolatedStringHandler.AppendFormatted((Object)(object)value.Worker.hands.heldProp == (Object)(object)prop);
						defaultInterpolatedStringHandler.AppendLiteral("; host observation, not remote ACK");
						AuditLog(key, defaultInterpolatedStringHandler.ToStringAndClear());
					}
					else if ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)value.Worker)
					{
						ManualLogSource logger3 = Plugin.Logger;
						BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(58, 1, ref flag2);
						if (flag2)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[ITEM STORAGE] holder changed for ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)prop).name);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; retrying native snatch");
						}
						logger3.LogDebug(val2);
						value.Attempts = 0;
						value.Stored = false;
						value.NextAttempt = Time.unscaledTime + 0.25f;
					}
					else if (!value.Stored || (Object)(object)val3 == (Object)(object)value.Worker)
					{
						if (!value.Stored)
						{
							DirectLocalTeleport(value.Worker, MarkerStorage());
						}
						value.Worker.playerNetworking.ServerDropPropAutomatic(true);
						BroadcastSnapshot((NetworkBehaviour)(object)value.Worker.playerNetworking);
						value.Stored = true;
						value.NextAttempt = Time.unscaledTime + 0.1f;
						AuditLog("storage-drop:" + ((Object)prop).GetInstanceID(), $"[ITEM STORAGE] awaiting manager drop: {((Object)prop).name} netId={((NetworkBehaviour)prop).netId} managerId={((NetworkBehaviour)value.Worker.playerNetworking).netId}");
					}
					else
					{
						PlaceLoose(prop, MarkerStorage(), Quaternion.identity);
						ManualLogSource logger4 = Plugin.Logger;
						BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(54, 4, ref flag2);
						if (flag2)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[ITEM STORAGE] completed ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)prop).name);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" netId=");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<uint>(((NetworkBehaviour)prop).netId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" managerId=");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<uint>(((NetworkBehaviour)value.Worker.playerNetworking).netId);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; attempts=");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(value.Attempts);
						}
						logger4.LogDebug(val2);
						ReleaseStorageWorker(value);
						itemStorageJobs.Remove(prop);
					}
					end_IL_0050:;
				}
				catch (Exception ex)
				{
					value.NextAttempt = Time.unscaledTime + 0.5f;
					AuditLog("storage-error:" + ((Object)item.Key).GetHashCode(), $"[ITEM STORAGE ERROR] item={((prop != null) ? ((Object)prop).name : null)} attempts={value.Attempts} stored={value.Stored}; retry in 0.5s: {ex.GetBaseException().Message}", warning: true);
				}
			}
			if (itemStorageJobs.Count != 0 || Time.unscaledTime < nextStorageCompletion)
			{
				return;
			}
			if (cleanupPending)
			{
				try
				{
					RestoreBorrowedProps();
					cleanupPending = false;
					return;
				}
				catch (Exception ex2)
				{
					nextStorageCompletion = Time.unscaledTime + 0.5f;
					AuditLog("cleanup-error", "[CLEANUP ERROR] retry in 0.5s: " + ex2.GetBaseException().Message, warning: true);
					return;
				}
			}
			if (finalThirtyPending)
			{
				finalThirtyPending = false;
				if (phase == Phase.Seeking)
				{
					GiveFinalSpeakers();
				}
			}
		}

		private void ReleaseStorageWorker(ItemStorageJob job)
		{
			if (!Object.ReferenceEquals((Object)(object)job.Worker, (Object)null))
			{
				if (CanTransportPlayer(job.Worker))
				{
					ReturnWorkerToStandby(job.Worker);
				}
				cleanupManagerItems.Remove(job.Worker);
			}
			job.Worker = null;
		}

		private void BeginRoundItemCleanup()
		{
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			finalThirtyPending = false;
			foreach (Prop value in normalItemAssignments.Values)
			{
				QueueItemStorage(value);
			}
			foreach (Prop value2 in lockedSpeakerAssignments.Values)
			{
				QueueItemStorage(value2);
			}
			foreach (PlayerCharacter item in Players())
			{
				if (!IsDummyManager(item))
				{
					PlayerHands hands = item.hands;
					if ((Object)(object)((hands != null) ? hands.heldProp : null) != (Object)null && IsGear(item.hands.heldProp) && !brushes.ContainsProp(item.hands.heldProp))
					{
						QueueItemStorage(item.hands.heldProp);
					}
				}
			}
			normalItemAssignments.Clear();
			lockedSpeakerAssignments.Clear();
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(55, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[CLEANUP] item jobs=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(itemStorageJobs.Count);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; transports continue independently");
			}
			logger.LogInfo(val);
		}

		private void RestoreSessionProps()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			int num = 0;
			bool flag = default(bool);
			foreach (KeyValuePair<Prop, PropOrigin> propOrigin in propOrigins)
			{
				Prop key = propOrigin.Key;
				if ((Object)(object)key == (Object)null)
				{
					continue;
				}
				try
				{
					PlaceLoose(key, propOrigin.Value.Position, propOrigin.Value.Rotation);
					if ((Object)(object)key.rb != (Object)null)
					{
						key.rb.useGravity = propOrigin.Value.Gravity;
						key.rb.isKinematic = propOrigin.Value.Kinematic;
					}
					num++;
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(20, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SESSION RESTORE] ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)key).name);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetBaseException().Message);
					}
					logger.LogWarning(val);
				}
			}
			ManualLogSource logger2 = Plugin.Logger;
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SESSION RESTORE] restored=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("/");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(propOrigins.Count);
			}
			logger2.LogInfo(val2);
		}

		private void ApplyFairPlayMods()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			if (!fairPlayApplied)
			{
				fairPlayApplied = true;
				nameTagsVisibleField = FindLoadedType("BigWalkNametags.Plugin")?.GetField("TagsVisible", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (nameTagsVisibleField?.GetValue(null) is bool flag)
				{
					nameTagsWereVisible = flag;
					nameTagsVisibleField.SetValue(null, false);
				}
				moderationNameTagsField = FindLoadedType("BigOrb.OrbBehaviour")?.GetField("NametagsOn", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (moderationNameTagsField?.GetValue(null) is bool flag2)
				{
					moderationNameTagsWereVisible = flag2;
					moderationNameTagsField.SetValue(null, false);
				}
				DisableBehaviour("modtolocatefriends.overlaything");
				ManualLogSource logger = Plugin.Logger;
				bool flag3 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(105, 1, ref flag3);
				if (flag3)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[FAIR PLAY] BigNameTags and Moderation Improvements nametags hidden; ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(fairPlayBehaviours.Count);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Player Locator overlay(s) disabled.");
				}
				logger.LogInfo(val);
			}
		}

		private void RestoreFairPlayMods()
		{
			if (!fairPlayApplied)
			{
				return;
			}
			try
			{
				if (nameTagsVisibleField != null)
				{
					nameTagsVisibleField.SetValue(null, nameTagsWereVisible);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("[FAIR PLAY] BigNameTags restore failed: " + ex.Message));
			}
			try
			{
				if (moderationNameTagsField != null)
				{
					moderationNameTagsField.SetValue(null, moderationNameTagsWereVisible);
				}
			}
			catch (Exception ex2)
			{
				Plugin.Logger.LogWarning((object)("[FAIR PLAY] Moderation Improvements nametags restore failed: " + ex2.Message));
			}
			foreach (Behaviour fairPlayBehaviour in fairPlayBehaviours)
			{
				if ((Object)(object)fairPlayBehaviour != (Object)null)
				{
					fairPlayBehaviour.enabled = true;
				}
			}
			fairPlayBehaviours.Clear();
			nameTagsVisibleField = null;
			moderationNameTagsField = null;
			fairPlayApplied = false;
		}

		private void DisableBehaviour(string typeName)
		{
			Type type = FindLoadedType(typeName);
			if (type == null)
			{
				return;
			}
			foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.From(type)))
			{
				Behaviour val = (Behaviour)(object)((item is Behaviour) ? item : null);
				if (val != null && val.enabled)
				{
					val.enabled = false;
					fairPlayBehaviours.Add(val);
				}
			}
		}

		private static Type FindLoadedType(string name)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(name, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		private static void StopUsingHeldProp(PlayerCharacter player, Prop prop)
		{
			//IL_0144: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			PlayerNetworking val = ((player != null) ? player.playerNetworking : null);
			if ((Object)(object)val == (Object)null || (Object)(object)prop == (Object)null)
			{
				return;
			}
			PlayerHands hands = player.hands;
			if ((Object)(object)((hands != null) ? hands.heldProp : null) != (Object)(object)prop || !NetworkServer.active)
			{
				return;
			}
			ShellReferenceWithActionNumber heldSwitch = val.heldSwitch;
			int num = Math.Max(heldSwitch.actionNumber, val.playerHeldInformation.actionNumber) + 1;
			PeckContext val2 = new PeckContext(player, prop)
			{
				actionNumber = num
			};
			try
			{
				UseHeldUpServer?.Invoke(val, new object[1] { val2 });
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("[ITEM RELEASE] held-up failed for " + ((Object)prop).name + ": " + ex.GetBaseException().Message));
			}
			try
			{
				ShellReference shellReference = heldSwitch.shellReference;
				if (shellReference.netId != 0 || shellReference.ticket != 0 || shellReference.index != 0)
				{
					ReleaseHeldSwitchServer?.Invoke(val, new object[3] { shellReference, val2, num });
				}
			}
			catch (Exception ex2)
			{
				Plugin.Logger.LogWarning((object)("[ITEM RELEASE] switch release failed for " + ((Object)prop).name + ": " + ex2.GetBaseException().Message));
			}
			val.NetworkheldSwitch = new ShellReferenceWithActionNumber(default(ShellReference), num);
			SetState(prop, 0);
			BroadcastSnapshot((NetworkBehaviour)(object)val);
			BroadcastSnapshot((NetworkBehaviour)(object)prop);
		}

		internal static PickupSnapshot BeforePickup(PlayerNetworking actor, PlayerHeldInformation held)
		{
			if (!ActiveHost || (Object)(object)actor == (Object)null || IsDummyManager(actor.playerCharacter) || !held.hasProp)
			{
				return null;
			}
			Prop prop = held.GetProp();
			if ((Object)(object)prop == (Object)null)
			{
				return null;
			}
			if (!ShouldBlockPropPickup(actor, held))
			{
				foreach (KeyValuePair<string, Prop> normalItemAssignment in Instance.normalItemAssignments)
				{
					if ((Object)(object)normalItemAssignment.Value == (Object)(object)prop)
					{
						return new PickupSnapshot
						{
							Prop = prop,
							Blocked = false,
							AssignmentOwner = normalItemAssignment.Key
						};
					}
				}
				return null;
			}
			Instance.AuditLog("pickup:" + Key(actor.playerCharacter), $"[PICKUP BLOCK] player={Key(actor.playerCharacter)} item={((Object)prop).name} action={held.actionNumber} phase={Instance.phase}");
			return new PickupSnapshot
			{
				Prop = prop
			};
		}

		internal static void CommitItemTransfer(PlayerNetworking actor, PickupSnapshot transfer)
		{
			if (!ActiveHost || (Object)(object)((actor != null) ? actor.playerCharacter : null) == (Object)null || transfer == null || transfer.Blocked)
			{
				return;
			}
			PlayerHands hands = actor.playerCharacter.hands;
			if (!((Object)(object)((hands != null) ? hands.heldProp : null) != (Object)(object)transfer.Prop))
			{
				string text = Key(actor.playerCharacter);
				Prop value;
				if (Instance.phase == Phase.SettingUp)
				{
					Instance.AuditLog("setup-transfer:" + text, "[ITEM TRANSFER] setup transfer ignored: " + transfer.AssignmentOwner + " -> " + text);
				}
				else if (!(text == transfer.AssignmentOwner) && !Instance.normalItemAssignments.ContainsKey(text) && !Instance.lockedSpeakerAssignments.ContainsKey(text) && Instance.normalItemAssignments.TryGetValue(transfer.AssignmentOwner, out value) && !((Object)(object)value != (Object)(object)transfer.Prop))
				{
					Instance.normalItemAssignments.Remove(transfer.AssignmentOwner);
					Instance.normalItemAssignments[text] = value;
					Plugin.Logger.LogDebug((object)("[ITEM TRANSFER] " + transfer.AssignmentOwner + " -> " + text));
				}
			}
		}

		private static void CorrectPredictedPickup(PlayerNetworking actor, PlayerHeldInformation rejected, Prop prop)
		{
			//IL_008f: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			NetworkConnectionToClient connectionToClient = ((NetworkBehaviour)actor).connectionToClient;
			if (connectionToClient == null || (object)connectionToClient == NetworkServer.localConnection || (Object)(object)prop == (Object)null)
			{
				return;
			}
			PlayerHeldInformation playerHeldInformation = actor.playerHeldInformation;
			if (playerHeldInformation.actionNumber > rejected.actionNumber)
			{
				BroadcastSnapshot((NetworkBehaviour)(object)actor, (NetworkConnection)(object)connectionToClient);
				return;
			}
			PlayerHeldInformation val = (PlayerHeldInformation)((!playerHeldInformation.hasProp) ? ((object)PlayerHeldInformation.DropFromSnatch()) : ((object)new PlayerHeldInformation(playerHeldInformation.GetProp())));
			val.actionNumber = rejected.actionNumber;
			actor.NetworkplayerHeldInformation = val;
			BroadcastSnapshot((NetworkBehaviour)(object)actor, (NetworkConnection)(object)connectionToClient);
			ShellReference propHomeShellReference = prop.propHomeShellReference;
			try
			{
				prop.propHomeShellReference = default(ShellReference);
				BroadcastSnapshot((NetworkBehaviour)(object)prop, (NetworkConnection)(object)connectionToClient);
			}
			finally
			{
				prop.propHomeShellReference = propHomeShellReference;
				BroadcastSnapshot((NetworkBehaviour)(object)prop, (NetworkConnection)(object)connectionToClient);
			}
			PlayerCharacter val2 = FindHolder(prop);
			if ((Object)(object)((val2 != null) ? val2.playerNetworking : null) != (Object)null && (Object)(object)val2.playerNetworking != (Object)(object)actor)
			{
				PlayerNetworking playerNetworking = val2.playerNetworking;
				PlayerHeldInformation val3 = PlayerHeldInformation.DropFromSnatch();
				val3.actionNumber = playerNetworking.playerHeldInformation.actionNumber;
				try
				{
					SendHeldView(playerNetworking, val3, (NetworkConnection)(object)connectionToClient);
				}
				finally
				{
					BroadcastSnapshot((NetworkBehaviour)(object)playerNetworking, (NetworkConnection)(object)connectionToClient);
				}
			}
			bool flag = Instance.IsProtectedWorldProp(prop);
			if (flag && (Object)(object)prop.currentHome == (Object)null && (Object)(object)val2 == (Object)null)
			{
				Vector3 val4 = ((Component)prop).transform.position;
				Quaternion rot = ((Component)prop).transform.rotation;
				if (Instance.markerPositions.TryGetValue(prop, out var value))
				{
					val4 = value;
					if (Instance.markerRotations.TryGetValue(prop, out var value2))
					{
						rot = value2;
					}
				}
				PlaceStatic(prop, val4, rot);
				Instance.AuditLog("prop-return:" + ((NetworkBehaviour)prop).netId, $"[PROTECTED PROP RETURN] prop={((Object)prop).name} netId={((NetworkBehaviour)prop).netId} position={val4} saved={Instance.markerPositions.ContainsKey(prop)}");
			}
			Instance.AuditLog("rollback:" + Key(actor.playerCharacter), $"[PICKUP ROLLBACK] player={Key(actor.playerCharacter)} prop={((Object)prop).name} netId={((NetworkBehaviour)prop).netId} action={val.actionNumber} previousHeld={playerHeldInformation.hasProp} staleDropData={playerHeldInformation.hasDropData} oldDropPosition={playerHeldInformation.dropPosition} protectedWorld={flag} pinned={(Object)(object)prop.currentHome != (Object)null}; fresh hand state sent");
		}

		private bool IsProtectedWorldProp(Prop prop)
		{
			if ((Object)(object)prop != (Object)null)
			{
				if (!IsSign(prop) && !buoys.ContainsProp(prop))
				{
					return markerPositions.ContainsKey(prop);
				}
				return true;
			}
			return false;
		}

		internal static bool BlockProtectedPropMovement(HouseNetworkTransform networkTransform)
		{
			if (!ActiveHost || !Instance.poolBuilt || (Object)(object)networkTransform == (Object)null)
			{
				return false;
			}
			Prop component = ((Component)networkTransform).GetComponent<Prop>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			int num;
			if (!Instance.IsProtectedWorldProp(component))
			{
				if (!((Object)(object)component.currentHome != (Object)null))
				{
					num = 0;
					goto IL_00df;
				}
				if (!Instance.bells.ContainsProp(component))
				{
					num = (Instance.belts.ContainsProp(component) ? 1 : 0);
					if (num == 0)
					{
						goto IL_00df;
					}
				}
				else
				{
					num = 1;
				}
			}
			else
			{
				num = 1;
			}
			Instance.AuditLog("prop-move:" + ((NetworkBehaviour)component).netId, $"[PROTECTED MOVE BLOCK] prop={((Object)component).name} netId={((NetworkBehaviour)component).netId}");
			goto IL_00df;
			IL_00df:
			return (byte)num != 0;
		}

		private static void SendHeldView(PlayerNetworking player, PlayerHeldInformation view, NetworkConnection recipient)
		{
			PlayerHeldInformation playerHeldInformation = player.playerHeldInformation;
			try
			{
				player.playerHeldInformation = view;
				BroadcastSnapshot((NetworkBehaviour)(object)player, recipient);
			}
			finally
			{
				player.playerHeldInformation = playerHeldInformation;
				((NetworkBehaviour)player).SetDirty();
			}
		}

		private static void BroadcastSnapshot(NetworkBehaviour behaviour, NetworkConnection recipient = null)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			NetworkIdentity val = ((behaviour != null) ? behaviour.netIdentity : null);
			if (((val != null) ? val.observers : null) == null)
			{
				return;
			}
			NetworkWriterPooled val2 = NetworkWriterPool.Get();
			NetworkWriterPooled val3 = NetworkWriterPool.Get();
			NetworkWriterPooled val4 = NetworkWriterPool.Get();
			float syncInterval = behaviour.syncInterval;
			try
			{
				behaviour.syncInterval = 0f;
				behaviour.SetDirty();
				val.SerializeServer(false, (NetworkWriter)(object)val2, (NetworkWriter)(object)val3);
				Enumerator<int, NetworkConnectionToClient> enumerator = val.observers.Values.GetEnumerator();
				while (enumerator.MoveNext())
				{
					NetworkConnectionToClient current = enumerator.Current;
					if (current != null && (object)current != NetworkServer.localConnection && (recipient == null || (object)current == recipient))
					{
						ArraySegment<byte> val5 = ((NetworkWriter)((current == val.connectionToClient) ? val2 : val3)).ToArraySegment();
						if (val5.Count != 0)
						{
							((NetworkWriter)val4).Reset();
							NetworkWriterExtensions.WriteUShort((NetworkWriter)(object)val4, NetworkMessageId<EntityStateMessage>.Id);
							GeneratedNetworkCode._Write_Mirror_EntityStateMessage((NetworkWriter)(object)val4, new EntityStateMessage
							{
								netId = val.netId,
								payload = val5
							});
							((NetworkConnection)current).Send(((NetworkWriter)val4).ToArraySegment(), 0);
						}
					}
				}
			}
			finally
			{
				behaviour.syncInterval = syncInterval;
				NetworkWriterPool.Return(val4);
				NetworkWriterPool.Return(val3);
				NetworkWriterPool.Return(val2);
			}
		}

		internal static bool MustDropCarriedPlayer(PlayerCharacter player)
		{
			if (!ActiveHost || (Object)(object)player == (Object)null || IsDummyManager(player))
			{
				return false;
			}
			string key = Key(player);
			PlayerHands hands = player.hands;
			if (!((Object)(object)((hands != null) ? hands.heldProp : null) != (Object)null) && !Instance.normalItemAssignments.ContainsKey(key))
			{
				return Instance.lockedSpeakerAssignments.ContainsKey(key);
			}
			return true;
		}

		internal static void EnforceExclusiveHands(PlayerCharacter player)
		{
			if (MustDropCarriedPlayer(player))
			{
				PlayerHands hands = player.hands;
				if ((Object)(object)((hands != null) ? hands.heldCharacter : null) != (Object)null)
				{
					player.playerNetworking.UserCode_CmdDropHeldPlayer();
				}
			}
		}

		public HideAndSeekTester(IntPtr pointer)
			: base(pointer)
		{
		}//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_039b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)


		internal static void ApplyEnabledSetting(bool enabled)
		{
			if (!enabled && !((Object)(object)Instance == (Object)null))
			{
				Instance.simpleVisible = false;
				Instance.setupVisible = false;
				Instance.SyncMenuCursor();
				if (Instance.sessionEnabled || Instance.remoteSessionEnabled)
				{
					Instance.ResetSession();
				}
			}
		}

		internal static bool IsDummyManager(PlayerCharacter player)
		{
			if ((Object)(object)player != (Object)null)
			{
				return (Object)(object)((Component)player).GetComponentInParent<DummyManagerMarker>(true) != (Object)null;
			}
			return false;
		}

		internal static void HandleSeekerPointCommand(PlayerNetworking networking, bool active)
		{
			HideAndSeekTester instance = Instance;
			if (!((Object)(object)instance == (Object)null) && NetworkServer.active && active && !((Object)(object)((networking != null) ? networking.playerCharacter : null) == (Object)null))
			{
				instance.TryLowCeilingCapture(networking.playerCharacter, "grab command");
			}
		}

		internal static bool ShouldBlockPropPickup(PlayerNetworking actor, PlayerHeldInformation held)
		{
			HideAndSeekTester instance = Instance;
			if (!ActiveHost || !instance.poolBuilt || (Object)(object)actor == (Object)null || IsDummyManager(actor.playerCharacter) || !held.hasProp)
			{
				return false;
			}
			Prop prop = held.GetProp();
			if ((Object)(object)prop == (Object)null)
			{
				return false;
			}
			string text = Key(actor.playerCharacter);
			if (instance.normalItemAssignments.TryGetValue(text, out var value) && (Object)(object)value != (Object)(object)prop)
			{
				return true;
			}
			if (instance.lockedSpeakerAssignments.TryGetValue(text, out var value2) && (Object)(object)value2 != (Object)(object)prop)
			{
				return true;
			}
			if (instance.lockedSpeakerAssignments.Values.ContainsProp(prop))
			{
				if (instance.lockedSpeakerAssignments.TryGetValue(text, out var value3))
				{
					return (Object)(object)value3 != (Object)(object)prop;
				}
				return true;
			}
			if (instance.itemStorageJobs.ContainsKey(prop))
			{
				return true;
			}
			if (instance.phase == Phase.SettingUp && instance.normalItemAssignments.Values.ContainsProp(prop) && (!instance.normalItemAssignments.TryGetValue(text, out var value4) || (Object)(object)value4 != (Object)(object)prop))
			{
				return true;
			}
			if (instance.normalItemAssignments.Values.ContainsProp(prop))
			{
				PlayerHands hands = actor.playerCharacter.hands;
				if ((Object)(object)((hands != null) ? hands.heldProp : null) != (Object)null && (Object)(object)actor.playerCharacter.hands.heldProp != (Object)(object)prop)
				{
					return true;
				}
			}
			if (instance.brushes.ContainsProp(prop) || ((Object)prop).name.StartsWith("SalonBrushProp", StringComparison.Ordinal))
			{
				return false;
			}
			if (instance.seekers.Contains(text))
			{
				return true;
			}
			if (instance.normalItemAssignments.Values.ContainsProp(prop))
			{
				if (instance.hiders.Contains(text))
				{
					return instance.caught.Contains(text);
				}
				return true;
			}
			if (instance.belts.ContainsProp(prop) || instance.bells.ContainsProp(prop) || instance.buoys.ContainsProp(prop) || instance.IsSign(prop) || instance.whiteboardOrigins.ContainsKey(prop))
			{
				return true;
			}
			if (!(((Object)prop).name != "MegaphoneProp") && instance.hiders.Contains(text))
			{
				return instance.caught.Contains(text);
			}
			return true;
		}

		internal static void RejectProtectedPropPickup(PlayerNetworking actor, PlayerHeldInformation rejected, PickupSnapshot repair)
		{
			if ((Object)(object)actor == (Object)null || !NetworkServer.active)
			{
				return;
			}
			try
			{
				CorrectPredictedPickup(actor, rejected, repair?.Prop ?? rejected.GetProp());
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("[PICKUP ROLLBACK ERROR] " + Key(actor.playerCharacter) + ": " + ex.GetBaseException().Message));
			}
		}

		private void Awake()
		{
			Instance = this;
		}

		private void Start()
		{
			LoadDefaultPresetIfUnconfigured();
			hasCenter = TryVector(Plugin.AreaPoint.Value, out center);
			hasSeeker = TryVector(Plugin.SeekerPoint.Value, out seekerSpawn);
			hasEndSpawn = TryVector(Plugin.EndPoint.Value, out endSpawn);
			hasGearStorage = TryVector(Plugin.GearStoragePoint.Value, out gearStorage);
			LoadSlots(Plugin.HiderSpawnSlots.Value, hiderSpawnSlots, 11);
			LoadSlots(Plugin.SeekerSpawnSlots.Value, seekerSpawnSlots, 11);
			LoadSlots(Plugin.EndSpawnSlots.Value, endSpawnSlots, 11);
			LoadSlots(Plugin.DummyStandbySlots.Value, standbySlots, 11);
			LoadSlots(Plugin.DraftSpawnSlots.Value, spawnPoints, 11);
			LoadSlots(Plugin.BorderPoints.Value, borderPoints, 20);
			LoadSlots(Plugin.PlayBorder.Value, playBorder, 20);
			LoadSlots(Plugin.SeekerBorder.Value, seekerBorder, 20);
			LoadSlots(Plugin.EndBorder.Value, endBorder, 20);
			LoadSlots(Plugin.DraftRecoveryPoints.Value, recoveryPoints, int.MaxValue);
			LoadSlots(Plugin.PlayRecoveryPoints.Value, playRecoveryPoints, int.MaxValue);
			LoadSigns(Plugin.InstructionSigns.Value);
			hasSeekerSign = TrySign(Plugin.SeekerSignTransform.Value, out seekerSignPosition, out seekerSignYaw);
			hasEndSign = TrySign(Plugin.EndSignTransform.Value, out endSignPosition, out endSignYaw);
			hasStatusSign = TrySign(Plugin.StatusSignTransform.Value, out statusSignPosition, out statusSignYaw);
			LoadPlayAreas();
			MarkSetupBaseline();
		}

		private static bool GameTextInputActive()
		{
			if (ControlsManager.textInputModeActive)
			{
				return true;
			}
			try
			{
				if (SignTextInput.IsSignInputActive())
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				TextChatInput instance = TextChatInput.instance;
				return instance != null && instance.inputIsOpen;
			}
			catch
			{
				return false;
			}
		}

		private void Update()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			ObserveSession();
			if (!Plugin.Enabled.Value)
			{
				simpleVisible = false;
				setupVisible = false;
				SyncMenuCursor();
				if (sessionEnabled || remoteSessionEnabled)
				{
					ResetSession();
				}
				return;
			}
			if (!NetworkClient.active || !NetworkClient.isConnected)
			{
				simpleVisible = false;
				setupVisible = false;
				SyncMenuCursor();
				return;
			}
			if (!GameTextInputActive() && Input.GetKeyDown(Plugin.MenuKey.Value))
			{
				simpleVisible = !simpleVisible;
			}
			if (phase == Phase.SettingUp || phase == Phase.Hiding || phase == Phase.Seeking)
			{
				setupVisible = false;
			}
			else if (!GameTextInputActive() && Input.GetKeyDown(Plugin.SetupKey.Value))
			{
				setupVisible = !setupVisible;
			}
			SyncMenuCursor();
			MaintainModNetworking();
			if (!NetworkServer.active)
			{
				if (remoteSessionEnabled)
				{
					ProcessRemoteClientTransport();
					UpdateFallProtection();
					if (Time.unscaledTime >= nextTimeApply)
					{
						nextTimeApply = Time.unscaledTime + 1f;
						ApplyRemoteTime();
					}
				}
			}
			else
			{
				if (!sessionEnabled)
				{
					return;
				}
				if (Time.unscaledTime >= nextTimeApply)
				{
					nextTimeApply = Time.unscaledTime + 1f;
					ApplyTime();
				}
				if (Time.unscaledTime >= nextDummyCorpseCleanup)
				{
					nextDummyCorpseCleanup = Time.unscaledTime + 0.25f;
					CleanupDummyCorpses();
				}
				KeepDummyOutOfRoster();
				UpdateFallProtection();
				ProtectManager();
				ProcessItemStorage();
				ProcessClientTransports();
				ProcessTransport();
				if (poolBuilt && Time.unscaledTime >= nextMarkerPin)
				{
					nextMarkerPin = Time.unscaledTime + 0.05f;
					MaintainMarkers();
				}
				if (phase == Phase.Ended)
				{
					if (hasEndSpawn && Time.unscaledTime >= nextScan)
					{
						nextScan = Time.unscaledTime + 0.05f;
						HandleConnections();
						MaintainCorpses();
						EnforceEndArea();
					}
				}
				else if (phase == Phase.SettingUp)
				{
					if (Time.unscaledTime >= nextScan)
					{
						nextScan = Time.unscaledTime + 0.05f;
						HandleConnections();
						MaintainCorpses();
						if (CheckNoHidersRemain())
						{
							return;
						}
					}
					if (EnsureSetupPositions())
					{
						BeginHiding();
					}
				}
				else
				{
					if (phase == Phase.Idle)
					{
						return;
					}
					if (Time.unscaledTime >= nextScan)
					{
						nextScan = Time.unscaledTime + 0.05f;
						HandleConnections();
						MaintainCorpses();
						if (CheckNoHidersRemain())
						{
							return;
						}
						EnforceBorders();
						MaintainRequiredItems();
					}
					if (phase == Phase.Seeking && seekerDeployment)
					{
						MaintainSeekerDeployment();
						return;
					}
					if (phase == Phase.Seeking && Time.unscaledTime >= nextCapture)
					{
						nextCapture = Time.unscaledTime + 0.05f;
						DetectCaptures();
					}
					if (phase == Phase.Seeking && !finalThirtyTriggered && remaining <= 30f)
					{
						BeginFinalThirty();
					}
					if (phase == Phase.Ended)
					{
						return;
					}
					remaining -= Time.unscaledDeltaTime;
					if (Time.unscaledTime >= nextTick)
					{
						nextTick = Time.unscaledTime + 1f;
						UpdateBoards();
					}
					if (remaining <= 0f)
					{
						if (phase == Phase.Hiding)
						{
							BeginSeeking();
						}
						else
						{
							EndRound("TIME UP - HIDERS WIN");
						}
					}
				}
			}
		}

		private void SyncMenuCursor()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (simpleVisible || setupVisible)
			{
				if (!menuCursorActive)
				{
					previousCursorLock = Cursor.lockState;
					previousCursorVisible = Cursor.visible;
					menuCursorActive = true;
				}
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
			else if (menuCursorActive)
			{
				Cursor.lockState = previousCursorLock;
				Cursor.visible = previousCursorVisible;
				menuCursorActive = false;
			}
		}

		private void OnGUI()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (simpleVisible)
			{
				simpleWindow = GUI.Window(730921, simpleWindow, WindowFunction.op_Implicit((Action<int>)DrawSimple), "Mady's HideNSeek");
			}
			if (setupVisible && phase != Phase.SettingUp && phase != Phase.Hiding && phase != Phase.Seeking)
			{
				setupWindow = GUI.Window(730922, setupWindow, WindowFunction.op_Implicit((Action<int>)DrawSetup), "Mady's HideNSeek Setup");
			}
			if (showSpawnDebug)
			{
				DrawSpawnDebug();
			}
		}

		private void DrawSimple(int id)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			simpleScroll = GUILayout.BeginScrollView(simpleScroll, (Il2CppReferenceArray<GUILayoutOption>)null);
			if ((Object)(object)LocalPlayer() == (Object)null || !NetworkServer.active)
			{
				GUILayout.Label(remoteSessionEnabled ? "Connected to host hide and seek. Setup is automatic." : "Host a lobby to configure hide and seek.", (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			else
			{
				GUILayout.Label(sessionEnabled ? $"Phase: {phase} | players: {Participants().Count}/11" : "Normal lobby - hide and seek is inactive.", (Il2CppReferenceArray<GUILayoutOption>)null);
				if (GUILayout.Button((sessionEnabled && poolBuilt && standbyManagers.Count == 11) ? "Setup complete" : "Setup", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SetupSession();
				}
				LiveFloat("Hide seconds", Plugin.HideTime, 5f, 300f);
				LiveFloat("Round seconds", Plugin.RoundTime, 15f, 1800f);
				LiveInt("Seeker count", Plugin.SeekerCount, 0, 3);
				DrawAreaSelector();
				Plugin.RandomItemChance.Value = GUILayout.HorizontalSlider(Mathf.Clamp(Plugin.RandomItemChance.Value, 0f, 100f), 0f, 100f, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Hider item chance: {Plugin.RandomItemChance.Value:0}%", (Il2CppReferenceArray<GUILayoutOption>)null);
				Plugin.FinalThirtySpeakers.Value = GUILayout.Toggle(Plugin.FinalThirtySpeakers.Value, "Speakers during final 30 seconds", Array.Empty<GUILayoutOption>());
				DrawItemCategoryControls();
				GUILayout.Label("Locked time: " + Plugin.TimeOfDay.Value, (Il2CppReferenceArray<GUILayoutOption>)null);
				GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
				TimeButton("Natural", LockedTime.Natural);
				TimeButton("Sunrise", LockedTime.Sunrise);
				TimeButton("Day", LockedTime.Day);
				TimeButton("Sunset", LockedTime.Sunset);
				TimeButton("Night", LockedTime.Night);
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
				GUI.enabled = sessionEnabled && poolBuilt && standbyManagers.Count == 11 && (phase == Phase.Idle || phase == Phase.Ended) && !cleanupPending;
				if (GUILayout.Button("Start round", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					StartRound();
				}
				GUI.enabled = sessionEnabled && (phase == Phase.Hiding || phase == Phase.Seeking || phase == Phase.SettingUp);
				if (GUILayout.Button("End round", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					EndRound("ROUND STOPPED");
				}
				GUI.enabled = true;
				GUILayout.EndHorizontal();
				if (GUILayout.Button("Join the Discord!", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					Application.OpenURL("https://discord.gg/5z3WvVhxCf");
				}
			}
			GUILayout.TextArea(status, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(65f) });
			GUILayout.EndScrollView();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
		}

		private void DrawSetup(int id)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			setupScroll = GUILayout.BeginScrollView(setupScroll, (Il2CppReferenceArray<GUILayoutOption>)null);
			PlayerCharacter val = LocalPlayer();
			if ((Object)(object)val == (Object)null || !NetworkServer.active)
			{
				GUILayout.Label(remoteSessionEnabled ? "Connected to host hide and seek. Setup is automatic." : "Host a lobby to configure hide and seek.", (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			else
			{
				DrawPresets();
				GUILayout.Label($"Play areas: {playAreas.Count} | seeker: {((seekerBorder.Count >= 4 && seekerSpawnSlots.Count == 11) ? "Fully Set" : "Missing")} | end: {((endBorder.Count >= 4 && endSpawnSlots.Count == 11) ? "Fully Set" : "Missing")}", (Il2CppReferenceArray<GUILayoutOption>)null);
				DrawAreaSelector();
				DrawAreaEditControls();
				GUILayout.Label("RIGHT-CLICK placement buttons to undo latest point.", (Il2CppReferenceArray<GUILayoutOption>)null);
				if (GUILayout.Button("Set gear storage", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					Save(((Component)val).transform.position, Plugin.GearStoragePoint, ref gearStorage, ref hasGearStorage, "gear storage");
				}
				if (RightClickedLastControl())
				{
					hasGearStorage = false;
					Plugin.GearStoragePoint.Value = "";
					status = "Gear storage cleared.";
				}
				if (GUILayout.Button((standbySlots.Count < 11) ? $"Set Manager standby {standbySlots.Count + 1}" : "Manager standbys: Fully Set (click to replace)", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					AddStandbyPoint(((Component)val).transform.position);
				}
				if (RightClickedLastControl())
				{
					UndoPoint(standbySlots, Plugin.DummyStandbySlots, "Manager standby");
				}
				GUILayout.Label($"Manager standby positions: {standbySlots.Count}/11", (Il2CppReferenceArray<GUILayoutOption>)null);
				if (GUILayout.Button("Set Instruction Sign", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					AddInstructionSign(val);
				}
				if (RightClickedLastControl())
				{
					instructionSignPositions.Clear();
					instructionSignYaws.Clear();
					SaveSigns();
					status = "Instruction sign cleared.";
				}
				GUILayout.Label("Instruction sign: " + ((instructionSignPositions.Count == 1) ? "Set" : "Missing") + " | facing = manager facing", (Il2CppReferenceArray<GUILayoutOption>)null);
				GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
				if (GUILayout.Button(hasSeekerSign ? "Seeker sign: Set" : "Set seeker sign", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveTimerSign(val, seeker: true);
				}
				if (RightClickedLastControl())
				{
					hasSeekerSign = false;
					Plugin.SeekerSignTransform.Value = "";
					status = "Seeker sign cleared.";
				}
				if (GUILayout.Button(hasEndSign ? "End sign: Set" : "Set end sign", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveTimerSign(val, seeker: false);
				}
				if (RightClickedLastControl())
				{
					hasEndSign = false;
					Plugin.EndSignTransform.Value = "";
					status = "End sign cleared.";
				}
				GUILayout.EndHorizontal();
				if (GUILayout.Button(AreaSignButtonLabel(), (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveDraftStatusSign(val);
				}
				if (RightClickedLastControl())
				{
					ClearAreaStatusSign();
				}
				GUILayout.Label("Instruction sign text", (Il2CppReferenceArray<GUILayoutOption>)null);
				string text = GUILayout.TextField(Plugin.InstructionSignText.Value, (Il2CppReferenceArray<GUILayoutOption>)null);
				if (text != Plugin.InstructionSignText.Value)
				{
					Plugin.InstructionSignText.Value = text;
					ApplyInstructionText();
				}
				GUILayout.Label($"Area draft: Spawn={spawnPoints.Count}/11 Border={borderPoints.Count}/20 Recover={recoveryPoints.Count}", (Il2CppReferenceArray<GUILayoutOption>)null);
				DrawSpawnSlots(val);
				GUI.enabled = spawnPoints.Count == 11 && borderPoints.Count >= 4 && recoveryPoints.Count > 0 && hasDraftStatusSign;
				if (GUILayout.Button((editingAreaIndex >= 0) ? "Save Edited Play Area" : "Save New Play Area", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveNewPlayArea();
				}
				if (RightClickedLastControl())
				{
					ClearAreaDraft();
				}
				GUI.enabled = true;
				GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
				if (GUILayout.Button("Spawn -> Seeker", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveSpawnDraft(Plugin.SeekerSpawnSlots, seekerSpawnSlots, Plugin.SeekerPoint, ref seekerSpawn, ref hasSeeker, "seeker");
				}
				if (GUILayout.Button("Spawn -> End", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveSpawnDraft(Plugin.EndSpawnSlots, endSpawnSlots, Plugin.EndPoint, ref endSpawn, ref hasEndSpawn, "end");
				}
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
				if (GUILayout.Button("Border -> Seeker", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveBorderDraft(Plugin.SeekerBorder, seekerBorder, "seeker");
				}
				if (GUILayout.Button("Border -> End", (Il2CppReferenceArray<GUILayoutOption>)null))
				{
					SaveBorderDraft(Plugin.EndBorder, endBorder, "end");
				}
				GUILayout.EndHorizontal();
				GUILayout.Label($"Buoys: {buoys.Count} found | {Mathf.Max(0, buoys.Count - StaticBorderCount() - WarningBuoyCount())} unused", (Il2CppReferenceArray<GUILayoutOption>)null);
				bool flag = GUILayout.Toggle(showSpawnDebug, "Show Objects", Array.Empty<GUILayoutOption>());
				if (flag != showSpawnDebug)
				{
					SetShowObjects(flag);
				}
				bool flag2 = GUILayout.Toggle(spawnDraftLights, "Spawn Draft Lights", Array.Empty<GUILayoutOption>());
				if (flag2 != spawnDraftLights)
				{
					if (!flag2)
					{
						ReturnBoundaryBuoys((phase != Phase.Idle && phase != Phase.Ended) ? (playBorder.Count + seekerBorder.Count + endBorder.Count) : 0, borderPoints.Count);
					}
					spawnDraftLights = flag2 && poolBuilt;
					if (poolBuilt)
					{
						PositionMarkers();
					}
					status = (spawnDraftLights ? "Draft lights spawned." : "Draft lights returned.");
				}
			}
			GUILayout.TextArea(status, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(65f) });
			GUILayout.EndScrollView();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
		}

		private void DrawSpawnDebug()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or mis