Decompiled source of Sector v1.2.0

Sector.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("Sector")]
[assembly: AssemblyTitle("Sector")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Empress.Sector
{
	internal static class SectorAccess
	{
		private static readonly FieldInfo? PlayerAvatarPlayerHealthField = AccessTools.Field(typeof(PlayerAvatar), "playerHealth");

		private static readonly FieldInfo? PlayerAvatarPlayerDeathHeadField = AccessTools.Field(typeof(PlayerAvatar), "playerDeathHead");

		private static readonly FieldInfo? PlayerAvatarPlayerNameField = AccessTools.Field(typeof(PlayerAvatar), "playerName");

		private static readonly FieldInfo? PlayerAvatarIsLocalField = AccessTools.Field(typeof(PlayerAvatar), "isLocal");

		private static readonly FieldInfo? PlayerAvatarIsDisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled");

		private static readonly FieldInfo? PlayerAvatarDeadSetField = AccessTools.Field(typeof(PlayerAvatar), "deadSet");

		private static readonly FieldInfo? PlayerHealthHealthField = AccessTools.Field(typeof(PlayerHealth), "health");

		private static readonly FieldInfo? PlayerHealthMaxHealthField = AccessTools.Field(typeof(PlayerHealth), "maxHealth");

		private static readonly FieldInfo? PlayerHealthGodModeField = AccessTools.Field(typeof(PlayerHealth), "godMode");

		private static readonly FieldInfo? PlayerControllerDebugEnergyField = AccessTools.Field(typeof(PlayerController), "DebugEnergy");

		private static readonly FieldInfo? PlayerControllerEnergyCurrentField = AccessTools.Field(typeof(PlayerController), "EnergyCurrent");

		private static readonly FieldInfo? PlayerControllerEnergyStartField = AccessTools.Field(typeof(PlayerController), "EnergyStart");

		private static readonly FieldInfo? PlayerControllerAvatarField = AccessTools.Field(typeof(PlayerController), "playerAvatarScript");

		private static readonly FieldInfo? PlayerDeathHeadInExtractionPointField = AccessTools.Field(typeof(PlayerDeathHead), "inExtractionPoint");

		private static readonly FieldInfo? EnemyDirectorDebugNoVisionField = AccessTools.Field(typeof(EnemyDirector), "debugNoVision");

		private static readonly FieldInfo? EnemyDirectorDebugNoSpawnIdlePauseField = AccessTools.Field(typeof(EnemyDirector), "debugNoSpawnIdlePause");

		private static readonly FieldInfo? EnemyDirectorDebugSpawnCloseField = AccessTools.Field(typeof(EnemyDirector), "debugSpawnClose");

		private static readonly FieldInfo? EnemyDirectorEnemiesSpawnedField = AccessTools.Field(typeof(EnemyDirector), "enemiesSpawned");

		private static readonly FieldInfo? EnemyParentSpawnedField = AccessTools.Field(typeof(EnemyParent), "Spawned");

		private static readonly FieldInfo? EnemyParentSetupDoneField = AccessTools.Field(typeof(EnemyParent), "SetupDone");

		private static readonly FieldInfo? EnemyParentFirstSpawnPointUsedField = AccessTools.Field(typeof(EnemyParent), "firstSpawnPointUsed");

		private static readonly FieldInfo? ValuableObjectPhysGrabObjectField = AccessTools.Field(typeof(ValuableObject), "physGrabObject");

		private static readonly FieldInfo? RoundDirectorExtractionPointCurrentField = AccessTools.Field(typeof(RoundDirector), "extractionPointCurrent");

		private static readonly FieldInfo? ExtractionPointCurrentStateField = AccessTools.Field(typeof(ExtractionPoint), "currentState");

		private static readonly FieldInfo? RunManagerDebugLevelField = AccessTools.Field(typeof(RunManager), "debugLevel");

		private static readonly FieldInfo? RunManagerGameOverField = AccessTools.Field(typeof(RunManager), "gameOver");

		private static readonly FieldInfo? MenuCursorMeshField = AccessTools.Field(typeof(MenuCursor), "mesh");

		private static readonly FieldInfo? MenuCursorShowTimerField = AccessTools.Field(typeof(MenuCursor), "showTimer");

		private static readonly FieldInfo? MenuCursorOverridePosTimerField = AccessTools.Field(typeof(MenuCursor), "overridePosTimer");

		private static readonly FieldInfo? CursorManagerUnlockTimerField = AccessTools.Field(typeof(CursorManager), "unlockTimer");

		public static PlayerHealth? GetPlayerHealth(PlayerAvatar? player)
		{
			return GetFieldValue<PlayerHealth>(PlayerAvatarPlayerHealthField, player);
		}

		public static PlayerDeathHead? GetPlayerDeathHead(PlayerAvatar? player)
		{
			return GetFieldValue<PlayerDeathHead>(PlayerAvatarPlayerDeathHeadField, player);
		}

		public static string GetPlayerName(PlayerAvatar? player)
		{
			return GetFieldValue(PlayerAvatarPlayerNameField, player, "Unknown operative");
		}

		public static bool IsPlayerLocal(PlayerAvatar? player)
		{
			return GetFieldValue(PlayerAvatarIsLocalField, player, fallback: false);
		}

		public static bool IsPlayerDisabled(PlayerAvatar? player)
		{
			return GetFieldValue(PlayerAvatarIsDisabledField, player, fallback: false);
		}

		public static bool IsPlayerDead(PlayerAvatar? player)
		{
			return GetFieldValue(PlayerAvatarDeadSetField, player, fallback: false);
		}

		public static int GetHealth(PlayerHealth? playerHealth)
		{
			return GetFieldValue(PlayerHealthHealthField, playerHealth, 0);
		}

		public static int GetMaxHealth(PlayerHealth? playerHealth)
		{
			return GetFieldValue(PlayerHealthMaxHealthField, playerHealth, 0);
		}

		public static void SetPlayerGodMode(PlayerHealth? playerHealth, bool enabled)
		{
			SetFieldValue(PlayerHealthGodModeField, playerHealth, enabled);
		}

		public static float GetEnergyCurrent(PlayerController? playerController)
		{
			return GetFieldValue(PlayerControllerEnergyCurrentField, playerController, 0f);
		}

		public static float GetEnergyStart(PlayerController? playerController)
		{
			return GetFieldValue(PlayerControllerEnergyStartField, playerController, 0f);
		}

		public static void SetEnergyCurrent(PlayerController? playerController, float value)
		{
			SetFieldValue(PlayerControllerEnergyCurrentField, playerController, value);
		}

		public static void SetDebugEnergy(PlayerController? playerController, bool enabled)
		{
			SetFieldValue(PlayerControllerDebugEnergyField, playerController, enabled);
		}

		public static PlayerAvatar? GetControllerAvatar(PlayerController? playerController)
		{
			return GetFieldValue<PlayerAvatar>(PlayerControllerAvatarField, playerController);
		}

		public static void SetInExtractionPoint(PlayerDeathHead? playerDeathHead, bool enabled)
		{
			SetFieldValue(PlayerDeathHeadInExtractionPointField, playerDeathHead, enabled);
		}

		public static bool GetEnemyNoVision(EnemyDirector? enemyDirector)
		{
			return GetFieldValue(EnemyDirectorDebugNoVisionField, enemyDirector, fallback: false);
		}

		public static void SetEnemyNoVision(EnemyDirector? enemyDirector, bool enabled)
		{
			SetFieldValue(EnemyDirectorDebugNoVisionField, enemyDirector, enabled);
		}

		public static bool GetEnemyNoSpawnIdlePause(EnemyDirector? enemyDirector)
		{
			return GetFieldValue(EnemyDirectorDebugNoSpawnIdlePauseField, enemyDirector, fallback: false);
		}

		public static void SetEnemyNoSpawnIdlePause(EnemyDirector? enemyDirector, bool enabled)
		{
			SetFieldValue(EnemyDirectorDebugNoSpawnIdlePauseField, enemyDirector, enabled);
		}

		public static bool GetEnemySpawnClose(EnemyDirector? enemyDirector)
		{
			return GetFieldValue(EnemyDirectorDebugSpawnCloseField, enemyDirector, fallback: false);
		}

		public static void SetEnemySpawnClose(EnemyDirector? enemyDirector, bool enabled)
		{
			SetFieldValue(EnemyDirectorDebugSpawnCloseField, enemyDirector, enabled);
		}

		public static List<EnemyParent> GetSpawnedEnemies(EnemyDirector? enemyDirector)
		{
			return GetFieldValue(EnemyDirectorEnemiesSpawnedField, enemyDirector, new List<EnemyParent>());
		}

		public static bool IsEnemySpawned(EnemyParent? enemyParent)
		{
			return GetFieldValue(EnemyParentSpawnedField, enemyParent, fallback: false);
		}

		public static void SetEnemySetupDone(EnemyParent? enemyParent, bool enabled)
		{
			SetFieldValue(EnemyParentSetupDoneField, enemyParent, enabled);
		}

		public static void SetEnemyFirstSpawnPointUsed(EnemyParent? enemyParent, bool enabled)
		{
			SetFieldValue(EnemyParentFirstSpawnPointUsedField, enemyParent, enabled);
		}

		public static GameObject? GetMenuCursorMesh(MenuCursor? menuCursor)
		{
			return GetFieldValue<GameObject>(MenuCursorMeshField, menuCursor);
		}

		public static void SetMenuCursorShowTimer(MenuCursor? menuCursor, float value)
		{
			SetFieldValue(MenuCursorShowTimerField, menuCursor, value);
		}

		public static void SetMenuCursorOverridePosTimer(MenuCursor? menuCursor, float value)
		{
			SetFieldValue(MenuCursorOverridePosTimerField, menuCursor, value);
		}

		public static void SetCursorUnlockTimer(CursorManager? cursorManager, float value)
		{
			SetFieldValue(CursorManagerUnlockTimerField, cursorManager, value);
		}

		public static PhysGrabObject? GetValuablePhysGrabObject(ValuableObject? valuableObject)
		{
			return GetFieldValue<PhysGrabObject>(ValuableObjectPhysGrabObjectField, valuableObject);
		}

		public static ExtractionPoint? GetRoundExtractionPointCurrent(RoundDirector? roundDirector)
		{
			return GetFieldValue<ExtractionPoint>(RoundDirectorExtractionPointCurrentField, roundDirector);
		}

		public static State GetExtractionPointState(ExtractionPoint? extractionPoint)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return GetFieldValue<State>(ExtractionPointCurrentStateField, extractionPoint, (State)0);
		}

		public static bool GetRunGameOver(RunManager? runManager)
		{
			return GetFieldValue(RunManagerGameOverField, runManager, fallback: false);
		}

		public static void SetRunDebugLevel(RunManager? runManager, Level? level)
		{
			SetFieldValue<Level>(RunManagerDebugLevelField, runManager, level);
		}

		private static T GetFieldValue<T>(FieldInfo? fieldInfo, object? instance, T fallback = default(T))
		{
			if (fieldInfo == null || instance == null)
			{
				return fallback;
			}
			try
			{
				return (T)((fieldInfo.GetValue(instance) is T val) ? ((object)val) : ((object)fallback));
			}
			catch
			{
				return fallback;
			}
		}

		private static void SetFieldValue<T>(FieldInfo? fieldInfo, object? instance, T value)
		{
			if (fieldInfo == null || instance == null)
			{
				return;
			}
			try
			{
				fieldInfo.SetValue(instance, value);
			}
			catch
			{
			}
		}
	}
	internal sealed class SectorActions
	{
		private const float InfiniteStrengthGrabValue = 100f;

		private readonly ManualLogSource _logger;

		private readonly SectorOverlayState _state;

		private readonly SectorCatalog _catalog;

		private PhysGrabber? _strengthGrabber;

		private float _strengthGrabberOriginal = 1f;

		public SectorActions(ManualLogSource logger, SectorOverlayState state, SectorCatalog catalog)
		{
			_logger = logger;
			_state = state;
			_catalog = catalog;
		}

		public void Tick()
		{
			try
			{
				ApplyLocalPowerState();
			}
			catch (Exception ex)
			{
				_logger.LogError((object)ex);
			}
		}

		public void ResetLocalPowerState()
		{
			PlayerHealth playerHealth = SectorAccess.GetPlayerHealth(PlayerAvatar.instance);
			if ((Object)(object)playerHealth != (Object)null)
			{
				SectorAccess.SetPlayerGodMode(playerHealth, enabled: false);
			}
			if ((Object)(object)PlayerController.instance != (Object)null)
			{
				SectorAccess.SetDebugEnergy(PlayerController.instance, enabled: false);
				PlayerController.instance.OverrideSpeed(1f, 0.05f);
			}
			_state.GodMode = false;
			_state.InfiniteEnergy = false;
			RestoreInfiniteStrength();
			_state.InfiniteStrength = false;
			_state.StickyBoost = false;
		}

		public SectorRuntimeSnapshot GetSnapshot()
		{
			List<PlayerAvatar> list = SectorGame.GetPlayers().ToList();
			PlayerHealth playerHealth = SectorAccess.GetPlayerHealth(SectorGame.GetLocalPlayer());
			PlayerController instance = PlayerController.instance;
			List<EnemyParent> spawnedEnemies = SectorAccess.GetSpawnedEnemies(EnemyDirector.instance);
			bool inRun = SectorGame.IsInPlayableRun();
			bool isHost = SemiFunc.IsMasterClientOrSingleplayer();
			object obj = RunManager.instance?.levelCurrent?.NarrativeName;
			if (obj == null)
			{
				RunManager instance2 = RunManager.instance;
				if (instance2 == null)
				{
					obj = null;
				}
				else
				{
					Level levelCurrent = instance2.levelCurrent;
					obj = ((levelCurrent != null) ? ((Object)levelCurrent).name : null);
				}
				if (obj == null)
				{
					obj = "No active level";
				}
			}
			return new SectorRuntimeSnapshot(inRun, isHost, (string)obj, list.Count, list.Count((PlayerAvatar player) => (Object)(object)player != (Object)null && !SectorAccess.IsPlayerDead(player) && !SectorAccess.IsPlayerDisabled(player)), list.Count((PlayerAvatar player) => (Object)(object)player != (Object)null && SectorAccess.IsPlayerDead(player)), spawnedEnemies.Count((EnemyParent enemy) => (Object)(object)enemy != (Object)null), Object.FindObjectsByType<ValuableObject>((FindObjectsSortMode)0).Length, SectorAccess.GetHealth(playerHealth), SectorAccess.GetMaxHealth(playerHealth), SectorAccess.GetEnergyCurrent(instance), SectorAccess.GetEnergyStart(instance), SectorAccess.GetEnemyNoVision(EnemyDirector.instance));
		}

		public void ExecuteCommand(string input)
		{
			string text = (input ?? string.Empty).Trim();
			if (string.IsNullOrEmpty(text))
			{
				_state.PushToast("Command deck is empty.");
				return;
			}
			string[] array = text.Split(' ', StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				_state.PushToast("Command deck is empty.");
				return;
			}
			switch (array[0].ToLowerInvariant())
			{
			case "help":
				_state.PushToast("Commands: spawn, heal, revive, despawn, destroy, noaggro, energy, god, strength, boost, truck, level.");
				return;
			case "spawn":
				ExecuteSpawnCommand(array);
				return;
			case "heal":
				ExecuteHealCommand(array);
				return;
			case "revive":
				ExecuteReviveCommand(array);
				return;
			case "despawn":
				if (array.Length >= 2 && array[1].Equals("enemies", StringComparison.OrdinalIgnoreCase))
				{
					DespawnEnemies();
					return;
				}
				break;
			case "destroy":
				if (array.Length >= 2 && array[1].Equals("enemies", StringComparison.OrdinalIgnoreCase))
				{
					DestroyEnemies();
					return;
				}
				break;
			case "noaggro":
				SetNoAggro(array.Length < 2 || ParseToggle(array[1], _state.NoAggro));
				return;
			case "energy":
				SetInfiniteEnergy(array.Length < 2 || ParseToggle(array[1], _state.InfiniteEnergy));
				return;
			case "god":
				SetGodMode(array.Length < 2 || ParseToggle(array[1], _state.GodMode));
				return;
			case "strength":
				SetInfiniteStrength(array.Length < 2 || ParseToggle(array[1], _state.InfiniteStrength));
				return;
			case "boost":
				ExecuteBoostCommand(array);
				return;
			case "truck":
				if (array.Length >= 2 && array[1].Equals("valuables", StringComparison.OrdinalIgnoreCase))
				{
					RecallValuablesToTruck();
					return;
				}
				break;
			case "level":
				ExecuteLevelCommand(array);
				return;
			}
			_state.PushToast("Unknown command: " + text);
		}

		public void Spawn(SectorSpawnEntry entry, int count)
		{
			count = Mathf.Clamp(count, 1, 25);
			if (EnsureHostTools("spawning"))
			{
				switch (entry.Kind)
				{
				case SectorSpawnKind.Enemy:
					SpawnEnemyEntry(entry, count);
					break;
				case SectorSpawnKind.Item:
					SpawnItemEntry(entry, count);
					break;
				case SectorSpawnKind.Valuable:
					SpawnValuableEntry(entry, count);
					break;
				}
			}
		}

		public void RefillLocalPlayer()
		{
			PlayerHealth playerHealth = SectorAccess.GetPlayerHealth(PlayerAvatar.instance);
			if ((Object)(object)playerHealth != (Object)null)
			{
				int num = Mathf.Max(0, SectorAccess.GetMaxHealth(playerHealth) - SectorAccess.GetHealth(playerHealth));
				if (num > 0)
				{
					playerHealth.Heal(num, true);
				}
			}
			if ((Object)(object)PlayerController.instance != (Object)null)
			{
				SectorAccess.SetEnergyCurrent(PlayerController.instance, SectorAccess.GetEnergyStart(PlayerController.instance));
			}
			_state.PushToast("Local player refilled.");
		}

		public void HealPlayer(PlayerAvatar? player)
		{
			PlayerHealth playerHealth = SectorAccess.GetPlayerHealth(player);
			if ((Object)(object)playerHealth == (Object)null)
			{
				_state.PushToast("Player health is unavailable.");
				return;
			}
			int num = Mathf.Max(0, SectorAccess.GetMaxHealth(playerHealth) - SectorAccess.GetHealth(playerHealth));
			if (num <= 0)
			{
				_state.PushToast(SectorAccess.GetPlayerName(player) + " is already full.");
				return;
			}
			playerHealth.HealOther(num, true);
			_state.PushToast("Healed " + SectorAccess.GetPlayerName(player) + ".");
		}

		public void HealAllPlayers()
		{
			int num = 0;
			foreach (PlayerAvatar player in SectorGame.GetPlayers())
			{
				PlayerHealth playerHealth = SectorAccess.GetPlayerHealth(player);
				if (!((Object)(object)playerHealth == (Object)null))
				{
					int num2 = Mathf.Max(0, SectorAccess.GetMaxHealth(playerHealth) - SectorAccess.GetHealth(playerHealth));
					if (num2 > 0)
					{
						playerHealth.HealOther(num2, true);
						num++;
					}
				}
			}
			_state.PushToast((num > 0) ? $"Healed {num} player(s)." : "Nobody needed healing.");
		}

		public void RevivePlayer(PlayerAvatar? player)
		{
			PlayerDeathHead playerDeathHead = SectorAccess.GetPlayerDeathHead(player);
			if ((Object)(object)player == (Object)null || !SectorAccess.IsPlayerDead(player) || (Object)(object)playerDeathHead == (Object)null)
			{
				_state.PushToast("That player is not in a revivable state.");
			}
			else if (EnsureHostTools("reviving"))
			{
				SectorAccess.SetInExtractionPoint(playerDeathHead, enabled: true);
				playerDeathHead.Revive();
				_state.PushToast("Revive requested for " + SectorAccess.GetPlayerName(player) + ".");
			}
		}

		public void ReviveAllPlayers()
		{
			if (!EnsureHostTools("reviving"))
			{
				return;
			}
			int num = 0;
			foreach (PlayerAvatar player in SectorGame.GetPlayers())
			{
				PlayerDeathHead playerDeathHead = SectorAccess.GetPlayerDeathHead(player);
				if (!((Object)(object)player == (Object)null) && SectorAccess.IsPlayerDead(player) && !((Object)(object)playerDeathHead == (Object)null))
				{
					SectorAccess.SetInExtractionPoint(playerDeathHead, enabled: true);
					playerDeathHead.Revive();
					num++;
				}
			}
			_state.PushToast((num > 0) ? $"Revive requested for {num} player(s)." : "No dead players found.");
		}

		public void DespawnEnemies()
		{
			if (!EnsureHostTools("enemy despawn"))
			{
				return;
			}
			int num = 0;
			if ((Object)(object)EnemyDirector.instance != (Object)null)
			{
				foreach (EnemyParent item in SectorAccess.GetSpawnedEnemies(EnemyDirector.instance).ToList())
				{
					if (!((Object)(object)item == (Object)null) && SectorAccess.IsEnemySpawned(item))
					{
						item.SpawnedTimerSet(0f);
						item.DespawnedTimerSet(10f, false);
						num++;
					}
				}
			}
			_state.PushToast((num > 0) ? $"Queued {num} enemy despawn(s)." : "No spawned enemies to despawn.");
		}

		public void DestroyEnemies()
		{
			if (!EnsureHostTools("enemy destroy"))
			{
				return;
			}
			int num = 0;
			if ((Object)(object)EnemyDirector.instance != (Object)null)
			{
				List<EnemyParent> spawnedEnemies = SectorAccess.GetSpawnedEnemies(EnemyDirector.instance);
				foreach (EnemyParent item in spawnedEnemies.ToList())
				{
					if (!((Object)(object)item == (Object)null))
					{
						spawnedEnemies.Remove(item);
						if (SemiFunc.IsMultiplayer())
						{
							PhotonNetwork.Destroy(((Component)item).gameObject);
						}
						else
						{
							Object.Destroy((Object)(object)((Component)item).gameObject);
						}
						num++;
					}
				}
			}
			_state.PushToast((num > 0) ? $"Destroyed {num} enemy object(s)." : "No enemies found.");
		}

		public void RecallValuablesToTruck()
		{
			//IL_00b9: 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_00c0: 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)
			if (!EnsureHostTools("valuable recall"))
			{
				return;
			}
			if ((Object)(object)TruckSafetySpawnPoint.instance == (Object)null)
			{
				_state.PushToast("Truck safety spawn is unavailable in this scene.");
				return;
			}
			ValuableObject[] array = Object.FindObjectsByType<ValuableObject>((FindObjectsSortMode)0);
			int num = 0;
			Vector3 val2 = default(Vector3);
			for (int i = 0; i < array.Length; i++)
			{
				ValuableObject val = array[i];
				PhysGrabObject valuablePhysGrabObject = SectorAccess.GetValuablePhysGrabObject(val);
				if (!((Object)(object)valuablePhysGrabObject == (Object)null))
				{
					int num2 = i % 8;
					int num3 = i / 8;
					float num4 = (float)num2 / 8f * MathF.PI * 2f;
					float num5 = 1.2f + (float)num3 * 0.8f;
					((Vector3)(ref val2))..ctor(Mathf.Cos(num4) * num5, 0.35f + (float)num3 * 0.1f, Mathf.Sin(num4) * num5);
					valuablePhysGrabObject.Teleport(((Component)TruckSafetySpawnPoint.instance).transform.position + val2, ((Component)TruckSafetySpawnPoint.instance).transform.rotation);
					val.DollarValueSetLogic();
					num++;
				}
			}
			_state.PushToast((num > 0) ? $"Recalled {num} valuable(s) to the truck." : "No valuables found.");
		}

		public void ForceEnemyInvestigateHere()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (EnsureHostTools("enemy redirect"))
			{
				PlayerAvatar localPlayer = SectorGame.GetLocalPlayer();
				if ((Object)(object)localPlayer == (Object)null)
				{
					_state.PushToast("Local player anchor is unavailable.");
					return;
				}
				SemiFunc.EnemyInvestigate(((Component)localPlayer).transform.position, 100f, true);
				_state.PushToast("Enemies redirected toward your position.");
			}
		}

		public void ToggleSpawnIdlePause()
		{
			if (EnsureHostTools("enemy idle timer toggle"))
			{
				if ((Object)(object)EnemyDirector.instance == (Object)null)
				{
					_state.PushToast("Enemy director is unavailable.");
					return;
				}
				bool flag = !SectorAccess.GetEnemyNoSpawnIdlePause(EnemyDirector.instance);
				SectorAccess.SetEnemyNoSpawnIdlePause(EnemyDirector.instance, flag);
				_state.PushToast(flag ? "Enemy spawn idle pause disabled." : "Enemy spawn idle pause restored.");
			}
		}

		public void SwitchLevel(string target)
		{
			string text = (target ?? string.Empty).Trim();
			if (string.IsNullOrEmpty(text))
			{
				_state.PushToast("Type a level target or use one of the quick switch buttons.");
			}
			else
			{
				if (!EnsureHostTools("level switching"))
				{
					return;
				}
				if ((Object)(object)RunManager.instance == (Object)null)
				{
					_state.PushToast("Run manager is unavailable.");
					return;
				}
				switch (text.ToLowerInvariant())
				{
				case "next":
					RunManager.instance.ChangeLevel(true, SemiFunc.RunIsArena(), (ChangeLevelType)0);
					_state.PushToast("Advancing to the next level.");
					break;
				case "random":
					RunManager.instance.ChangeLevel(false, false, (ChangeLevelType)1);
					_state.PushToast("Switching to a random run level.");
					break;
				case "refresh":
					RunManager.instance.RestartScene();
					if (!SemiFunc.RunIsTutorial())
					{
						SemiFunc.OnSceneSwitch(SectorAccess.GetRunGameOver(RunManager.instance), false);
					}
					_state.PushToast("Refreshing the current level.");
					break;
				case "shop":
					RunManager.instance.ChangeLevel(false, false, (ChangeLevelType)5);
					_state.PushToast("Switching to the shop.");
					break;
				case "recording":
					RunManager.instance.ChangeLevel(false, false, (ChangeLevelType)6);
					_state.PushToast("Switching to the recording level.");
					break;
				case "lobby":
					SwitchToSpecificLevel(RunManager.instance.levelLobby);
					break;
				case "arena":
					SwitchToSpecificLevel(RunManager.instance.levelArena);
					break;
				default:
				{
					Level val = FindLevelMatch(text);
					if ((Object)(object)val == (Object)null)
					{
						_state.PushToast("No level matched '" + text + "'.");
					}
					else
					{
						SwitchToSpecificLevel(val);
					}
					break;
				}
				}
			}
		}

		public void AddMoney(int amount)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Invalid comparison between Unknown and I4
			if (amount <= 0)
			{
				_state.PushToast("Money amount must be above zero.");
			}
			else
			{
				if (!EnsureCurrencyTools())
				{
					return;
				}
				int num = SemiFunc.StatGetRunCurrency();
				int num2 = ((num > int.MaxValue - amount) ? int.MaxValue : (num + amount));
				SemiFunc.StatSetRunCurrency(num2);
				CurrencyUI instance = CurrencyUI.instance;
				if (instance != null)
				{
					instance.FetchCurrency();
				}
				if (SemiFunc.RunIsShop())
				{
					RunManager instance2 = RunManager.instance;
					if (instance2 != null)
					{
						instance2.ChangeLevel(false, false, (ChangeLevelType)5);
					}
				}
				else if (SemiFunc.RunIsLevel() && (int)SectorAccess.GetExtractionPointState(SectorAccess.GetRoundExtractionPointCurrent(RoundDirector.instance)) > 1)
				{
					RunManager instance3 = RunManager.instance;
					if (instance3 != null)
					{
						instance3.ChangeLevel(false, false, (ChangeLevelType)0);
					}
				}
				_state.PushToast("Added " + SemiFunc.DollarGetString(amount) + ". Cash now " + SemiFunc.DollarGetString(num2) + ".");
			}
		}

		public void AddMoney(string amountText)
		{
			if (!int.TryParse((amountText ?? string.Empty).Trim(), out var result))
			{
				_state.PushToast("Enter a whole number for cash.");
			}
			else
			{
				AddMoney(result);
			}
		}

		public IReadOnlyList<string> GetLevelSuggestions(string search)
		{
			if (RunManager.instance?.levels == null)
			{
				return Array.Empty<string>();
			}
			IEnumerable<Level> source = RunManager.instance.levels.Where((Level level) => (Object)(object)level != (Object)null);
			string trimmedSearch = (search ?? string.Empty).Trim();
			if (!string.IsNullOrEmpty(trimmedSearch))
			{
				source = source.Where((Level level) => LevelMatches(level, trimmedSearch, allowPartial: true));
			}
			return (from name in (from name in source.Select(GetLevelDisplayName)
					where !string.IsNullOrWhiteSpace(name)
					select name).Distinct<string>(StringComparer.OrdinalIgnoreCase)
				orderby name
				select name).Take(8).ToList();
		}

		public void SetGodMode(bool enabled)
		{
			_state.GodMode = enabled;
			_state.PushToast(enabled ? "God mode armed for the local player." : "God mode disabled.");
		}

		public void SetInfiniteEnergy(bool enabled)
		{
			_state.InfiniteEnergy = enabled;
			_state.PushToast(enabled ? "Infinite energy armed." : "Infinite energy disabled.");
		}

		public void SetInfiniteStrength(bool enabled)
		{
			_state.InfiniteStrength = enabled;
			if (!enabled)
			{
				RestoreInfiniteStrength();
			}
			_state.PushToast(enabled ? "Infinite strength armed. Pick up whatever you want." : "Infinite strength disabled.");
		}

		public void SetNoAggro(bool enabled)
		{
			_state.NoAggro = enabled;
			if ((Object)(object)EnemyDirector.instance != (Object)null)
			{
				SectorAccess.SetEnemyNoVision(EnemyDirector.instance, enabled);
			}
			_state.PushToast(enabled ? "Enemy vision disabled." : "Enemy vision restored.");
		}

		private void ApplyLocalPowerState()
		{
			PlayerAvatar localPlayer = SectorGame.GetLocalPlayer();
			PlayerHealth playerHealth = SectorAccess.GetPlayerHealth(localPlayer);
			if ((Object)(object)playerHealth != (Object)null)
			{
				SectorAccess.SetPlayerGodMode(playerHealth, _state.GodMode);
			}
			if ((Object)(object)PlayerController.instance != (Object)null)
			{
				SectorAccess.SetDebugEnergy(PlayerController.instance, _state.InfiniteEnergy);
				if (_state.InfiniteEnergy)
				{
					SectorAccess.SetEnergyCurrent(PlayerController.instance, SectorAccess.GetEnergyStart(PlayerController.instance));
				}
				ApplyInfiniteStrength(localPlayer);
				if (_state.StickyBoost && _state.SpeedMultiplier > 1.01f)
				{
					PlayerController.instance.OverrideSpeed(_state.SpeedMultiplier, 0.25f);
				}
			}
			if ((Object)(object)EnemyDirector.instance != (Object)null)
			{
				SectorAccess.SetEnemyNoVision(EnemyDirector.instance, _state.NoAggro);
			}
		}

		private void ApplyInfiniteStrength(PlayerAvatar? localPlayer)
		{
			PhysGrabber val = localPlayer?.physGrabber ?? PhysGrabber.instance;
			if (!_state.InfiniteStrength)
			{
				RestoreInfiniteStrength();
			}
			else if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)_strengthGrabber != (Object)(object)val)
				{
					RestoreInfiniteStrength();
					_strengthGrabber = val;
					_strengthGrabberOriginal = Mathf.Max(1f, val.grabStrength);
				}
				val.grabStrength = 100f;
			}
		}

		private void RestoreInfiniteStrength()
		{
			PhysGrabber strengthGrabber = _strengthGrabber;
			if ((Object)(object)strengthGrabber == (Object)null)
			{
				_strengthGrabber = null;
				_strengthGrabberOriginal = 1f;
			}
			else
			{
				strengthGrabber.grabStrength = Mathf.Max(1f, _strengthGrabberOriginal);
				_strengthGrabber = null;
				_strengthGrabberOriginal = 1f;
			}
		}

		private void ExecuteSpawnCommand(string[] tokens)
		{
			if (tokens.Length < 3)
			{
				_state.PushToast("Usage: spawn enemy|item|valuable <name> [count]");
				return;
			}
			int result = 1;
			bool num = int.TryParse(tokens[^1], out result);
			result = Mathf.Clamp(result, 1, 25);
			string text = tokens[1].ToLowerInvariant();
			int startIndex = 2;
			int num2 = (num ? (tokens.Length - 3) : (tokens.Length - 2));
			if (num2 < 1)
			{
				_state.PushToast("Spawn command is missing a target name.");
				return;
			}
			string text2 = string.Join(" ", tokens, startIndex, num2);
			if (!TryParseKind(text, out var kind))
			{
				_state.PushToast("Unknown spawn type: " + text);
				return;
			}
			SectorSpawnEntry sectorSpawnEntry = _catalog.FindBestMatch(kind, text2);
			if (sectorSpawnEntry == null)
			{
				_state.PushToast("No " + text + " matched '" + text2 + "'.");
			}
			else
			{
				Spawn(sectorSpawnEntry, result);
			}
		}

		private void ExecuteHealCommand(string[] tokens)
		{
			if (tokens.Length < 2)
			{
				_state.PushToast("Usage: heal me|all");
				return;
			}
			string text = tokens[1].ToLowerInvariant();
			if (!(text == "me"))
			{
				if (text == "all")
				{
					HealAllPlayers();
				}
				else
				{
					_state.PushToast("Usage: heal me|all");
				}
			}
			else
			{
				RefillLocalPlayer();
			}
		}

		private void ExecuteReviveCommand(string[] tokens)
		{
			if (tokens.Length < 2)
			{
				_state.PushToast("Usage: revive all");
			}
			else if (tokens[1].Equals("all", StringComparison.OrdinalIgnoreCase))
			{
				ReviveAllPlayers();
			}
			else
			{
				_state.PushToast("Usage: revive all");
			}
		}

		private void ExecuteBoostCommand(string[] tokens)
		{
			float result;
			if (tokens.Length < 2)
			{
				_state.StickyBoost = !_state.StickyBoost;
				_state.PushToast(_state.StickyBoost ? $"Sticky boost enabled at {_state.SpeedMultiplier:0.0}x." : "Sticky boost disabled.");
			}
			else if (tokens[1].Equals("off", StringComparison.OrdinalIgnoreCase))
			{
				_state.StickyBoost = false;
				_state.PushToast("Sticky boost disabled.");
			}
			else if (float.TryParse(tokens[1], out result))
			{
				_state.SpeedMultiplier = Mathf.Clamp(result, 1f, 4f);
				_state.StickyBoost = _state.SpeedMultiplier > 1.01f;
				_state.PushToast(_state.StickyBoost ? $"Sticky boost set to {_state.SpeedMultiplier:0.0}x." : "Sticky boost disabled.");
			}
			else
			{
				_state.PushToast("Usage: boost <multiplier>|off");
			}
		}

		private void ExecuteLevelCommand(string[] tokens)
		{
			if (tokens.Length < 2)
			{
				_state.PushToast("Usage: level <next|random|refresh|shop|lobby|arena|recording|name>");
			}
			else
			{
				SwitchLevel(string.Join(" ", tokens.Skip(1)));
			}
		}

		private void SpawnEnemyEntry(SectorSpawnEntry entry, int count)
		{
			//IL_00b9: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)entry.EnemySetup == (Object)null || entry.EnemySetup.spawnObjects == null || entry.EnemySetup.spawnObjects.Count == 0)
			{
				_state.PushToast("Enemy profile '" + entry.DisplayName + "' has no spawn objects.");
				return;
			}
			List<LevelPoint> list = SectorGame.GetSpawnPoints(count).ToList();
			if (list.Count == 0)
			{
				_state.PushToast("No usable level points are available yet.");
				return;
			}
			int num = 0;
			bool enemySpawnClose = SectorAccess.GetEnemySpawnClose(EnemyDirector.instance);
			if ((Object)(object)EnemyDirector.instance != (Object)null)
			{
				SectorAccess.SetEnemySpawnClose(EnemyDirector.instance, enabled: true);
			}
			try
			{
				for (int i = 0; i < count; i++)
				{
					Vector3 val = ((Component)list[Mathf.Min(i, list.Count - 1)]).transform.position + Vector3.up * 0.1f;
					foreach (PrefabRef spawnObject in entry.EnemySetup.spawnObjects)
					{
						if (spawnObject == null || !spawnObject.IsValid())
						{
							continue;
						}
						GameObject val2 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.InstantiateRoomObject(spawnObject.ResourcePath, val, Quaternion.identity, (byte)0, (object[])null) : Object.Instantiate<GameObject>(spawnObject.Prefab, val, Quaternion.identity));
						if ((Object)(object)val2 == (Object)null)
						{
							continue;
						}
						EnemyParent component = val2.GetComponent<EnemyParent>();
						if ((Object)(object)component != (Object)null)
						{
							SectorAccess.SetEnemySetupDone(component, enabled: true);
							SectorAccess.SetEnemyFirstSpawnPointUsed(component, enabled: true);
							Enemy componentInChildren = ((Component)component).GetComponentInChildren<Enemy>();
							if (componentInChildren != null)
							{
								componentInChildren.EnemyTeleported(val);
							}
						}
					}
					num++;
				}
			}
			finally
			{
				if ((Object)(object)EnemyDirector.instance != (Object)null)
				{
					SectorAccess.SetEnemySpawnClose(EnemyDirector.instance, enemySpawnClose);
				}
			}
			_state.PushToast($"Spawned {num} '{entry.DisplayName}' pack(s).");
		}

		private void SpawnItemEntry(SectorSpawnEntry entry, int count)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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)
			if (entry.Item?.prefab == null || !entry.Item.prefab.IsValid())
			{
				_state.PushToast("Item '" + entry.DisplayName + "' is missing a valid prefab reference.");
				return;
			}
			List<LevelPoint> list = SectorGame.GetSpawnPoints(count).ToList();
			if (list.Count == 0)
			{
				_state.PushToast("No usable level points are available yet.");
				return;
			}
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				LevelPoint obj = list[Mathf.Min(i, list.Count - 1)];
				Vector3 val = ((Component)obj).transform.position + Vector3.up * (1f + (float)i * 0.03f);
				Quaternion val2 = ((Component)obj).transform.rotation * entry.Item.spawnRotationOffset;
				if (SemiFunc.IsMultiplayer())
				{
					PhotonNetwork.InstantiateRoomObject(entry.Item.prefab.ResourcePath, val, val2, (byte)0, (object[])null);
				}
				else
				{
					Object.Instantiate<GameObject>(entry.Item.prefab.Prefab, val, val2);
				}
				num++;
			}
			_state.PushToast($"Spawned {num} '{entry.DisplayName}' item(s).");
		}

		private void SpawnValuableEntry(SectorSpawnEntry entry, int count)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (entry.PrefabRef == null || !entry.PrefabRef.IsValid())
			{
				_state.PushToast("Valuable '" + entry.DisplayName + "' is missing a valid prefab reference.");
				return;
			}
			List<LevelPoint> list = SectorGame.GetSpawnPoints(count).ToList();
			if (list.Count == 0)
			{
				_state.PushToast("No usable level points are available yet.");
				return;
			}
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				LevelPoint val = list[Mathf.Min(i, list.Count - 1)];
				Vector3 val2 = ((Component)val).transform.position + Vector3.up * (1f + (float)i * 0.04f);
				GameObject obj = (SemiFunc.IsMultiplayer() ? PhotonNetwork.InstantiateRoomObject(entry.PrefabRef.ResourcePath, val2, ((Component)val).transform.rotation, (byte)0, (object[])null) : Object.Instantiate<GameObject>(entry.PrefabRef.Prefab, val2, ((Component)val).transform.rotation));
				if (obj != null)
				{
					ValuableObject component = obj.GetComponent<ValuableObject>();
					if (component != null)
					{
						component.DollarValueSetLogic();
					}
				}
				num++;
			}
			_state.PushToast($"Spawned {num} '{entry.DisplayName}' valuable(s).");
		}

		private bool EnsureHostTools(string label)
		{
			if (!SectorGame.IsInPlayableRun())
			{
				_state.PushToast("Start or join a live run before using " + label + ".");
				return false;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				_state.PushToast(label + " is host or singleplayer only.");
				return false;
			}
			return true;
		}

		private void SwitchToSpecificLevel(Level? level)
		{
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)level == (Object)null)
			{
				_state.PushToast("That level target is unavailable.");
				return;
			}
			string levelDisplayName = GetLevelDisplayName(level);
			SectorAccess.SetRunDebugLevel(RunManager.instance, level);
			try
			{
				RunManager.instance.ChangeLevel(false, false, (ChangeLevelType)0);
			}
			finally
			{
				SectorAccess.SetRunDebugLevel(RunManager.instance, null);
			}
			_state.PushToast("Switching to " + levelDisplayName + ".");
		}

		private bool EnsureCurrencyTools()
		{
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)StatsManager.instance == (Object)null)
			{
				_state.PushToast("Cash controls are unavailable right now.");
				return false;
			}
			if (SemiFunc.IsMainMenu() && !SemiFunc.RunIsLobbyMenu())
			{
				_state.PushToast("Join a lobby or start singleplayer before editing cash.");
				return false;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				_state.PushToast("Cash editing is host or singleplayer only.");
				return false;
			}
			return true;
		}

		private static Level? FindLevelMatch(string target)
		{
			string target2 = target;
			if (RunManager.instance?.levels == null)
			{
				return null;
			}
			Level val = ((IEnumerable<Level>)RunManager.instance.levels).FirstOrDefault((Func<Level, bool>)((Level level) => LevelMatches(level, target2, allowPartial: false)));
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return ((IEnumerable<Level>)RunManager.instance.levels).FirstOrDefault((Func<Level, bool>)((Level level) => LevelMatches(level, target2, allowPartial: true)));
		}

		private static bool LevelMatches(Level? level, string target, bool allowPartial)
		{
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			string value = target.Trim().ToLowerInvariant();
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			foreach (string item in EnumerateLevelTerms(level))
			{
				string text = item.ToLowerInvariant();
				if (text.Equals(value, StringComparison.Ordinal))
				{
					return true;
				}
				if (allowPartial && text.Contains(value, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static IEnumerable<string> EnumerateLevelTerms(Level? level)
		{
			if (!((Object)(object)level == (Object)null))
			{
				string text = level.NarrativeName?.Trim();
				if (!string.IsNullOrEmpty(text))
				{
					yield return text;
				}
				string text2 = CleanLevelName(((Object)level).name);
				if (!string.IsNullOrEmpty(text2))
				{
					yield return text2;
				}
				string text3 = ((Object)level).name?.Trim();
				if (!string.IsNullOrEmpty(text3))
				{
					yield return text3;
				}
			}
		}

		private static string GetLevelDisplayName(Level? level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return "Unknown level";
			}
			string text = level.NarrativeName?.Trim();
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			string text2 = CleanLevelName(((Object)level).name);
			if (!string.IsNullOrEmpty(text2))
			{
				return text2;
			}
			return "Unknown level";
		}

		private static string CleanLevelName(string? rawName)
		{
			string text = (rawName ?? string.Empty).Trim();
			if (!text.StartsWith("Level - ", StringComparison.OrdinalIgnoreCase))
			{
				return text;
			}
			return text.Substring("Level - ".Length).Trim();
		}

		private static bool ParseToggle(string token, bool currentValue)
		{
			switch (token.ToLowerInvariant())
			{
			case "1":
			case "enabled":
			case "on":
			case "true":
			case "enable":
				return true;
			case "0":
			case "disable":
			case "off":
			case "false":
			case "disabled":
				return false;
			default:
				return !currentValue;
			}
		}

		private static bool TryParseKind(string token, out SectorSpawnKind kind)
		{
			switch (token.ToLowerInvariant())
			{
			case "enemy":
			case "enemies":
				kind = SectorSpawnKind.Enemy;
				return true;
			case "item":
			case "items":
				kind = SectorSpawnKind.Item;
				return true;
			case "valuable":
			case "valuables":
				kind = SectorSpawnKind.Valuable;
				return true;
			default:
				kind = SectorSpawnKind.Enemy;
				return false;
			}
		}
	}
	internal static class SectorGame
	{
		public static bool IsInPlayableRun()
		{
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)LevelGenerator.Instance == (Object)null)
			{
				return false;
			}
			if (!LevelGenerator.Instance.Generated)
			{
				return false;
			}
			if (SemiFunc.IsMainMenu() || SemiFunc.RunIsLobbyMenu() || SemiFunc.RunIsTutorial())
			{
				return false;
			}
			return true;
		}

		public static PlayerAvatar? GetLocalPlayer()
		{
			PlayerAvatar controllerAvatar = SectorAccess.GetControllerAvatar(PlayerController.instance);
			if ((Object)(object)controllerAvatar != (Object)null)
			{
				return controllerAvatar;
			}
			return PlayerAvatar.instance;
		}

		public static IEnumerable<PlayerAvatar> GetPlayers()
		{
			return SemiFunc.PlayerGetList() ?? new List<PlayerAvatar>();
		}

		public static IEnumerable<LevelPoint> GetSpawnPoints(int desiredCount)
		{
			//IL_0029: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!IsInPlayableRun())
			{
				return Array.Empty<LevelPoint>();
			}
			PlayerAvatar? localPlayer = GetLocalPlayer();
			Vector3 anchor = ((localPlayer != null) ? ((Component)localPlayer).transform.position : Vector3.zero);
			List<LevelPoint> list = SemiFunc.LevelPointsGetAll();
			if (list == null || list.Count == 0)
			{
				return Array.Empty<LevelPoint>();
			}
			return (from point in list
				where (Object)(object)point != (Object)null
				orderby Vector3.Distance(((Component)point).transform.position, anchor)
				select point).Take(Mathf.Max(desiredCount, 1)).ToList();
		}
	}
	internal sealed class SectorCatalog
	{
		private static readonly Regex EnemyPrefix = new Regex("^Enemy (- )?", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static readonly Regex ItemPrefix = new Regex("^Item ", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static readonly Regex ValuablePrefix = new Regex("^Valuable ", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private readonly ManualLogSource _logger;

		private readonly List<SectorSpawnEntry> _entries = new List<SectorSpawnEntry>();

		private float _nextRefreshTime;

		public int EnemyCount => _entries.Count((SectorSpawnEntry entry) => entry.Kind == SectorSpawnKind.Enemy);

		public int ItemCount => _entries.Count((SectorSpawnEntry entry) => entry.Kind == SectorSpawnKind.Item);

		public int ValuableCount => _entries.Count((SectorSpawnEntry entry) => entry.Kind == SectorSpawnKind.Valuable);

		public SectorCatalog(ManualLogSource logger)
		{
			_logger = logger;
		}

		public IReadOnlyList<SectorSpawnEntry> GetEntries(SectorSpawnKind kind, string search)
		{
			RefreshIfNeeded();
			string text = (search ?? string.Empty).Trim();
			if (string.IsNullOrEmpty(text))
			{
				return (from entry in _entries
					where entry.Kind == kind
					orderby entry.DisplayName
					select entry).ToList();
			}
			string normalized = text.ToLowerInvariant();
			return (from entry in _entries
				where entry.Kind == kind && entry.SearchText.Contains(normalized, StringComparison.Ordinal)
				orderby entry.DisplayName
				select entry).ToList();
		}

		public SectorSpawnEntry? FindBestMatch(SectorSpawnKind kind, string query)
		{
			RefreshIfNeeded();
			if (string.IsNullOrWhiteSpace(query))
			{
				return null;
			}
			string trimmed = query.Trim();
			string lowered = trimmed.ToLowerInvariant();
			SectorSpawnEntry sectorSpawnEntry = _entries.FirstOrDefault((SectorSpawnEntry entry) => entry.Kind == kind && (entry.Key.Equals(lowered, StringComparison.Ordinal) || entry.DisplayName.Equals(trimmed, StringComparison.OrdinalIgnoreCase)));
			if (sectorSpawnEntry != null)
			{
				return sectorSpawnEntry;
			}
			return (from entry in _entries
				where entry.Kind == kind
				orderby entry.DisplayName
				select entry).FirstOrDefault((SectorSpawnEntry entry) => entry.Key.StartsWith(lowered, StringComparison.Ordinal) || entry.SearchText.Contains(lowered, StringComparison.Ordinal));
		}

		private void RefreshIfNeeded()
		{
			if (_entries.Count == 0 || !(Time.unscaledTime < _nextRefreshTime))
			{
				_nextRefreshTime = Time.unscaledTime + 2.5f;
				BuildCatalog();
			}
		}

		private void BuildCatalog()
		{
			_entries.Clear();
			try
			{
				BuildEnemyEntries();
				BuildItemEntries();
				BuildValuableEntries();
			}
			catch (Exception ex)
			{
				_logger.LogError((object)ex);
			}
		}

		private void BuildEnemyEntries()
		{
			if ((Object)(object)EnemyDirector.instance == (Object)null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (EnemySetup item in Enumerate(EnemyDirector.instance.enemiesDifficulty1).Concat(Enumerate(EnemyDirector.instance.enemiesDifficulty2)).Concat(Enumerate(EnemyDirector.instance.enemiesDifficulty3)))
			{
				if (!((Object)(object)item == (Object)null))
				{
					string text = CleanEnemyName(((Object)item).name);
					string text2 = text.ToLowerInvariant();
					if (hashSet.Add(text2))
					{
						_entries.Add(new SectorSpawnEntry(SectorSpawnKind.Enemy, text2, text, "Enemy profile", BuildSearchText(text, ((Object)item).name, "enemy"), item));
					}
				}
			}
		}

		private void BuildItemEntries()
		{
			if ((Object)(object)StatsManager.instance == (Object)null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (Item value in StatsManager.instance.itemDictionary.Values)
			{
				if (!((Object)(object)value == (Object)null) && !value.disabled)
				{
					string text = CleanItemName(((Object)value).name);
					string text2 = text.ToLowerInvariant();
					if (hashSet.Add(text2))
					{
						_entries.Add(new SectorSpawnEntry(SectorSpawnKind.Item, text2, text, ((object)(itemType)(ref value.itemType)).ToString(), BuildSearchText(text, value.itemName, value.description, ((object)(itemType)(ref value.itemType)).ToString(), "item"), null, value));
					}
				}
			}
		}

		private void BuildValuableEntries()
		{
			if ((Object)(object)RunManager.instance == (Object)null || RunManager.instance.levels == null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (Level level in RunManager.instance.levels)
			{
				if ((Object)(object)level == (Object)null || level.ValuablePresets == null)
				{
					continue;
				}
				foreach (LevelValuables valuablePreset in level.ValuablePresets)
				{
					foreach (PrefabRef item in EnumerateValuables(valuablePreset))
					{
						if (item != null && item.IsValid())
						{
							string text = CleanValuableName(item.PrefabName);
							string text2 = text.ToLowerInvariant();
							if (hashSet.Add(text2))
							{
								_entries.Add(new SectorSpawnEntry(SectorSpawnKind.Valuable, text2, text, level.NarrativeName, BuildSearchText(text, item.PrefabName, level.NarrativeName, "valuable"), null, null, item));
							}
						}
					}
				}
			}
		}

		private static IEnumerable<T> Enumerate<T>(IEnumerable<T>? source)
		{
			return source ?? Array.Empty<T>();
		}

		private static IEnumerable<PrefabRef> EnumerateValuables(LevelValuables? preset)
		{
			if ((Object)(object)preset == (Object)null)
			{
				yield break;
			}
			foreach (PrefabRef item in Enumerate(preset.tiny))
			{
				yield return item;
			}
			foreach (PrefabRef item2 in Enumerate(preset.small))
			{
				yield return item2;
			}
			foreach (PrefabRef item3 in Enumerate(preset.medium))
			{
				yield return item3;
			}
			foreach (PrefabRef item4 in Enumerate(preset.big))
			{
				yield return item4;
			}
			foreach (PrefabRef item5 in Enumerate(preset.wide))
			{
				yield return item5;
			}
			foreach (PrefabRef item6 in Enumerate(preset.tall))
			{
				yield return item6;
			}
			foreach (PrefabRef item7 in Enumerate(preset.veryTall))
			{
				yield return item7;
			}
		}

		private static string BuildSearchText(params string?[] fragments)
		{
			return string.Join(" ", fragments.Where((string fragment) => !string.IsNullOrWhiteSpace(fragment))).ToLowerInvariant();
		}

		private static string CleanEnemyName(string rawName)
		{
			return EnemyPrefix.Replace(rawName ?? string.Empty, string.Empty).Trim();
		}

		private static string CleanItemName(string rawName)
		{
			return ItemPrefix.Replace(rawName ?? string.Empty, string.Empty).Trim();
		}

		private static string CleanValuableName(string rawName)
		{
			return ValuablePrefix.Replace(rawName ?? string.Empty, string.Empty).Trim();
		}
	}
	internal enum SectorTab
	{
		Ops,
		Spawn,
		Players,
		World,
		Scene
	}
	internal enum SectorSpawnKind
	{
		Enemy,
		Item,
		Valuable
	}
	internal sealed class SectorSpawnEntry
	{
		public SectorSpawnKind Kind { get; }

		public string Key { get; }

		public string DisplayName { get; }

		public string Subtitle { get; }

		public string SearchText { get; }

		public EnemySetup? EnemySetup { get; }

		public Item? Item { get; }

		public PrefabRef? PrefabRef { get; }

		public SectorSpawnEntry(SectorSpawnKind kind, string key, string displayName, string subtitle, string searchText, EnemySetup? enemySetup = null, Item? item = null, PrefabRef? prefabRef = null)
		{
			Kind = kind;
			Key = key;
			DisplayName = displayName;
			Subtitle = subtitle;
			SearchText = searchText;
			EnemySetup = enemySetup;
			Item = item;
			PrefabRef = prefabRef;
		}
	}
	internal sealed class SectorOverlayState
	{
		private readonly List<string> _activity = new List<string>();

		public bool Visible;

		public Rect WindowRect = new Rect(72f, 72f, 1180f, 720f);

		public SectorTab ActiveTab;

		public SectorSpawnKind ActiveSpawnKind;

		public Vector2 OpsScroll;

		public Vector2 SpawnScroll;

		public Vector2 PlayersScroll;

		public Vector2 WorldScroll;

		public Vector2 SceneScroll;

		public string SpawnSearch = string.Empty;

		public string CommandText = string.Empty;

		public string SpawnAmountText = "1";

		public string ObjectSearch = string.Empty;

		public string LevelSwitchText = string.Empty;

		public string MoneyAddText = "1000";

		public bool GodMode;

		public bool InfiniteEnergy;

		public bool InfiniteStrength;

		public bool StickyBoost;

		public bool NoAggro;

		public float SpeedMultiplier = 2f;

		public bool ShowLevelPoints;

		public bool ShowMeshLabels;

		public bool ShowMeshBounds;

		public int SelectedSceneObjectId;

		public string FlashMessage = string.Empty;

		public float FlashUntil;

		public IReadOnlyList<string> Activity => _activity;

		public int SpawnAmount
		{
			get
			{
				if (int.TryParse(SpawnAmountText, out var result))
				{
					return Mathf.Clamp(result, 1, 25);
				}
				return 1;
			}
		}

		public void PushToast(string message)
		{
			if (!string.IsNullOrWhiteSpace(message))
			{
				FlashMessage = message.Trim();
				FlashUntil = Time.unscaledTime + 4.5f;
				_activity.Insert(0, $"[{DateTime.Now:HH:mm:ss}] {FlashMessage}");
				if (_activity.Count > 10)
				{
					_activity.RemoveRange(10, _activity.Count - 10);
				}
			}
		}
	}
	internal readonly struct SectorRuntimeSnapshot
	{
		public bool InRun { get; }

		public bool IsHost { get; }

		public string LevelName { get; }

		public int Players { get; }

		public int AlivePlayers { get; }

		public int DeadPlayers { get; }

		public int Enemies { get; }

		public int Valuables { get; }

		public int LocalHealth { get; }

		public int LocalMaxHealth { get; }

		public float LocalEnergy { get; }

		public float LocalEnergyMax { get; }

		public bool NoAggroEnabled { get; }

		public SectorRuntimeSnapshot(bool inRun, bool isHost, string levelName, int players, int alivePlayers, int deadPlayers, int enemies, int valuables, int localHealth, int localMaxHealth, float localEnergy, float localEnergyMax, bool noAggroEnabled)
		{
			InRun = inRun;
			IsHost = isHost;
			LevelName = levelName;
			Players = players;
			AlivePlayers = alivePlayers;
			DeadPlayers = deadPlayers;
			Enemies = enemies;
			Valuables = valuables;
			LocalHealth = localHealth;
			LocalMaxHealth = localMaxHealth;
			LocalEnergy = localEnergy;
			LocalEnergyMax = localEnergyMax;
			NoAggroEnabled = noAggroEnabled;
		}
	}
	internal readonly struct SectorSceneSnapshot
	{
		public bool FreecamActive { get; }

		public bool CopyForgeActive { get; }

		public int TrackedObjects { get; }

		public int LevelPoints { get; }

		public int MeshObjects { get; }

		public string ModeLabel { get; }

		public SectorSceneSnapshot(bool freecamActive, bool copyForgeActive, int trackedObjects, int levelPoints, int meshObjects, string modeLabel)
		{
			FreecamActive = freecamActive;
			CopyForgeActive = copyForgeActive;
			TrackedObjects = trackedObjects;
			LevelPoints = levelPoints;
			MeshObjects = meshObjects;
			ModeLabel = modeLabel;
		}
	}
	internal sealed class SectorSceneObjectInfo
	{
		public int InstanceId { get; }

		public string Name { get; }

		public string Path { get; }

		public string Category { get; }

		public Vector3 Position { get; }

		public bool Active { get; }

		public int RendererCount { get; }

		public bool HasCollider { get; }

		public bool HasPhotonView { get; }

		public bool CanDelete { get; }

		public bool CanCopy { get; }

		public SectorSceneObjectInfo(int instanceId, string name, string path, string category, Vector3 position, bool active, int rendererCount, bool hasCollider, bool hasPhotonView, bool canDelete, bool canCopy)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			InstanceId = instanceId;
			Name = name;
			Path = path;
			Category = category;
			Position = position;
			Active = active;
			RendererCount = rendererCount;
			HasCollider = hasCollider;
			HasPhotonView = hasPhotonView;
			CanDelete = canDelete;
			CanCopy = canCopy;
		}
	}
	internal sealed class SectorSceneQueryResult
	{
		public IReadOnlyList<SectorSceneObjectInfo> Entries { get; }

		public int TotalMatches { get; }

		public SectorSceneQueryResult(IReadOnlyList<SectorSceneObjectInfo> entries, int totalMatches)
		{
			Entries = entries;
			TotalMatches = totalMatches;
		}
	}
	[BepInPlugin("empress.repo.sector", "Sector", "0.1.0")]
	internal sealed class SectorPlugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "empress.repo.sector";

		internal const string PluginName = "Sector";

		internal const string PluginVersion = "0.1.0";

		private ConfigEntry<KeyboardShortcut>? _toggleKey;

		private SectorOverlayState? _state;

		private SectorCatalog? _catalog;

		private SectorActions? _actions;

		private SectorSceneController? _scene;

		private SectorUi? _ui;

		private bool _cursorCaptured;

		private bool _previousCursorVisible;

		private CursorLockMode _previousCursorLockState;

		private Texture2D? _sectorCursorTexture;

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Toggle the Sector control window.");
			_state = new SectorOverlayState();
			_catalog = new SectorCatalog(((BaseUnityPlugin)this).Logger);
			_actions = new SectorActions(((BaseUnityPlugin)this).Logger, _state, _catalog);
			_scene = new SectorSceneController(((BaseUnityPlugin)this).Logger, _state);
			_ui = new SectorUi(((BaseUnityPlugin)this).Logger, _state, _catalog, _actions, _scene, _toggleKey.Value);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Sector booted. Press F8 to open the Empress control suite.");
		}

		private void Update()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (_state != null && _actions != null && _scene != null && _toggleKey != null)
			{
				KeyboardShortcut value = _toggleKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					_state.Visible = !_state.Visible;
					_state.PushToast(_state.Visible ? "Sector window opened." : "Sector window hidden.");
				}
				if (_state.Visible && Input.GetKeyDown((KeyCode)27))
				{
					_state.Visible = false;
				}
				_actions.Tick();
				_scene.Tick(_state.Visible);
				if (_state.Visible)
				{
					ApplySectorCursor();
				}
				else
				{
					RestoreCursorState();
				}
			}
		}

		private void OnGUI()
		{
			_ui?.Draw();
			_scene?.DrawOverlay();
		}

		private void OnDestroy()
		{
			RestoreCursorState();
			_scene?.Reset();
			_actions?.ResetLocalPowerState();
		}

		private void CaptureCursorState()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!_cursorCaptured)
			{
				_previousCursorVisible = Cursor.visible;
				_previousCursorLockState = Cursor.lockState;
				_cursorCaptured = true;
			}
		}

		private void RestoreCursorState()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (_cursorCaptured)
			{
				Cursor.SetCursor((Texture2D)null, Vector2.zero, (CursorMode)0);
				Cursor.visible = _previousCursorVisible;
				Cursor.lockState = _previousCursorLockState;
				if ((_previousCursorVisible || (int)_previousCursorLockState == 0) && (Object)(object)MenuCursor.instance != (Object)null)
				{
					MenuCursor.instance.Show();
				}
				_cursorCaptured = false;
			}
		}

		private void ApplySectorCursor()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			CaptureCursorState();
			EnsureSectorCursorTexture();
			SuppressGameCursorSystems();
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			Cursor.SetCursor(_sectorCursorTexture, new Vector2((float)((Texture)_sectorCursorTexture).width * 0.5f, (float)((Texture)_sectorCursorTexture).height * 0.5f), (CursorMode)0);
		}

		private void SuppressGameCursorSystems()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			SectorAccess.SetCursorUnlockTimer(CursorManager.instance, -1234f);
			if (!((Object)(object)MenuCursor.instance == (Object)null))
			{
				SectorAccess.SetMenuCursorShowTimer(MenuCursor.instance, 0f);
				SectorAccess.SetMenuCursorOverridePosTimer(MenuCursor.instance, 0f);
				GameObject menuCursorMesh = SectorAccess.GetMenuCursorMesh(MenuCursor.instance);
				if ((Object)(object)menuCursorMesh != (Object)null && menuCursorMesh.activeSelf)
				{
					menuCursorMesh.SetActive(false);
				}
				((Component)MenuCursor.instance).transform.localScale = Vector3.zero;
			}
		}

		private void EnsureSectorCursorTexture()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_sectorCursorTexture != (Object)null)
			{
				return;
			}
			_sectorCursorTexture = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)0,
				hideFlags = (HideFlags)61
			};
			for (int i = 0; i < ((Texture)_sectorCursorTexture).height; i++)
			{
				for (int j = 0; j < ((Texture)_sectorCursorTexture).width; j++)
				{
					float num = (float)j - 15.5f;
					float num2 = (float)i - 15.5f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					Color clear = Color.clear;
					if (num3 <= 2.25f)
					{
						((Color)(ref clear))..ctor(1f, 0.94f, 0.94f, 1f);
					}
					else if (num3 <= 5.2f)
					{
						((Color)(ref clear))..ctor(0.98f, 0.22f, 0.16f, 1f);
					}
					else if (num3 <= 7.4f)
					{
						((Color)(ref clear))..ctor(1f, 0.2f, 0.16f, 0.4f);
					}
					_sectorCursorTexture.SetPixel(j, i, clear);
				}
			}
			_sectorCursorTexture.Apply();
		}
	}
	internal sealed class SectorSceneController
	{
		private readonly struct PlacementState
		{
			public Vector3 Position { get; }

			public Quaternion Rotation { get; }

			public PlacementState(Vector3 position, Quaternion rotation)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Position = position;
				Rotation = rotation;
			}
		}

		private const HideFlags RuntimeHideFlags = 61;

		private const float FreezeRefresh = 0.2f;

		private const float SceneRefreshInterval = 0.75f;

		private const int MaxBrowserEntries = 140;

		private const int MaxLabelEntries = 48;

		private const int MaxBoundsEntries = 28;

		private readonly ManualLogSource _logger;

		private readonly SectorOverlayState _state;

		private readonly List<SectorSceneObjectInfo> _sceneObjects = new List<SectorSceneObjectInfo>();

		private readonly Dictionary<int, WeakReference<GameObject>> _sceneObjectRefs = new Dictionary<int, WeakReference<GameObject>>();

		private float _nextSceneRefreshTime;

		private Transform? _freecamRoot;

		private Transform? _freecamRestoreParent;

		private Vector3 _freecamRestoreLocalPosition;

		private Quaternion _freecamRestoreLocalRotation;

		private float _freecamYaw;

		private float _freecamPitch;

		private bool _freecamActive;

		private int _copySourceId;

		private string _copySourceName = string.Empty;

		private GameObject? _copyPreview;

		private float _copyDistance = 5f;

		private float _copyHeightOffset;

		private Vector3 _copyRotationEuler;

		private GUIStyle? _overlayLabelStyle;

		private GUIStyle? _overlayHintStyle;

		private Texture2D? _overlayLineTexture;

		private Texture2D? _blueOrbGlowTexture;

		private Texture2D? _blueOrbCoreTexture;

		private Texture2D? _orangeOrbGlowTexture;

		private Texture2D? _orangeOrbCoreTexture;

		private GameObject? _worldVisualRoot;

		private Material? _worldLineMaterial;

		private Material? _worldOrbMaterial;

		private readonly List<LineRenderer> _worldLinePool = new List<LineRenderer>();

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

		private bool IsCopyForgeActive
		{
			get
			{
				if ((Object)(object)_copyPreview != (Object)null)
				{
					return _copySourceId != 0;
				}
				return false;
			}
		}

		public SectorSceneController(ManualLogSource logger, SectorOverlayState state)
		{
			_logger = logger;
			_state = state;
		}

		public SectorSceneSnapshot GetSnapshot()
		{
			RefreshSceneCache();
			List<LevelPoint> list = SemiFunc.LevelPointsGetAll();
			int meshObjects = _sceneObjects.Count((SectorSceneObjectInfo info) => info.RendererCount > 0);
			string modeLabel = (IsCopyForgeActive ? ("COPY FORGE: " + _copySourceName) : (_freecamActive ? "FREECAM ACTIVE" : "SCENE TOOLING READY"));
			return new SectorSceneSnapshot(_freecamActive, IsCopyForgeActive, _sceneObjects.Count, list?.Count ?? 0, meshObjects, modeLabel);
		}

		public SectorSceneQueryResult QueryObjects(string search)
		{
			RefreshSceneCache();
			IEnumerable<SectorSceneObjectInfo> source = _sceneObjects;
			string text = (search ?? string.Empty).Trim();
			if (!string.IsNullOrEmpty(text))
			{
				string lowered = text.ToLowerInvariant();
				source = source.Where((SectorSceneObjectInfo info) => info.Name.Contains(lowered, StringComparison.OrdinalIgnoreCase) || info.Path.Contains(lowered, StringComparison.OrdinalIgnoreCase) || info.Category.Contains(lowered, StringComparison.OrdinalIgnoreCase));
			}
			List<SectorSceneObjectInfo> list = source.ToList();
			return new SectorSceneQueryResult(list.Take(140).ToList(), list.Count);
		}

		public SectorSceneObjectInfo? GetSelectedObject()
		{
			if (_state.SelectedSceneObjectId == 0)
			{
				return null;
			}
			GameObject val = ResolveSceneObject(_state.SelectedSceneObjectId);
			if (!((Object)(object)val == (Object)null))
			{
				return BuildSceneInfo(val);
			}
			return null;
		}

		public void Tick(bool menuVisible)
		{
			try
			{
				if (!SectorGame.IsInPlayableRun())
				{
					SetWorldVisualsVisible(visible: false);
					if (_freecamActive || IsCopyForgeActive)
					{
						Reset();
					}
					return;
				}
				if (menuVisible || _freecamActive || IsCopyForgeActive)
				{
					KeepPlayerFrozen();
				}
				if (IsCopyForgeActive)
				{
					EnsureFreecamCamera();
					UpdateFreecamMotion(menuVisible);
					UpdateCopyForge(menuVisible);
				}
				else if (_freecamActive)
				{
					EnsureFreecamCamera();
					UpdateFreecamMotion(menuVisible);
					if (!menuVisible && Input.GetKeyDown((KeyCode)27))
					{
						ExitFreecam();
						_state.PushToast("Freecam disengaged.");
					}
				}
				else if ((Object)(object)_freecamRoot != (Object)null)
				{
					RestoreMainCamera();
				}
				UpdateWorldVisuals();
			}
			catch (Exception ex)
			{
				_logger.LogError((object)ex);
				Reset();
				_state.PushToast("Scene tooling hit an error and reset safely.");
			}
		}

		public void DrawOverlay()
		{
			if (SectorGame.IsInPlayableRun())
			{
				EnsureOverlayStyles();
				if (_freecamActive)
				{
					DrawHintBox(IsCopyForgeActive ? ("COPY FORGE: " + _copySourceName + "  |  Left Click place  |  Right Click / Esc cancel  |  Mouse Wheel distance  |  Q/E rotate  |  R/F height") : "FREECAM ACTIVE  |  WASD move  |  Space / Ctrl vertical  |  Shift boost  |  Esc exit  |  F8 reopen Sector", 16f);
				}
				_ = IsCopyForgeActive;
			}
		}

		public void ToggleFreecam()
		{
			if (_freecamActive)
			{
				bool isCopyForgeActive = IsCopyForgeActive;
				ExitFreecam();
				_state.PushToast(isCopyForgeActive ? "Copy forge aborted." : "Freecam disengaged.");
			}
			else if (!EnsureFreecamCamera())
			{
				_state.PushToast("Main camera is unavailable for freecam.");
			}
			else
			{
				_freecamActive = true;
				_state.Visible = false;
				_state.PushToast("Freecam engaged. Press F8 to reopen Sector.");
			}
		}

		public void FocusObject(int instanceId)
		{
			GameObject val = ResolveSceneObject(instanceId);
			if ((Object)(object)val == (Object)null)
			{
				RefreshSceneCache(force: true);
				_state.PushToast("That scene object is no longer available.");
				return;
			}
			if (!EnsureFreecamCamera())
			{
				_state.PushToast("Main camera is unavailable for focus jump.");
				return;
			}
			_state.SelectedSceneObjectId = instanceId;
			_freecamActive = true;
			PositionFreecamForTarget(val);
			_state.Visible = false;
			_state.PushToast("Focused freecam on " + ((Object)val).name + ".");
		}

		public void DeleteObject(int instanceId)
		{
			GameObject val = ResolveSceneObject(instanceId);
			if ((Object)(object)val == (Object)null)
			{
				RefreshSceneCache(force: true);
				_state.PushToast("That scene object is already gone.");
				return;
			}
			if (IsProtectedObject(val))
			{
				_state.PushToast(((Object)val).name + " is protected from deletion.");
				return;
			}
			_state.SelectedSceneObjectId = instanceId;
			try
			{
				PhotonView component = val.GetComponent<PhotonView>();
				if (SemiFunc.IsMultiplayer() && (Object)(object)component != (Object)null)
				{
					PhotonNetwork.Destroy(val);
				}
				else
				{
					Object.Destroy((Object)(object)val);
				}
				RefreshSceneCache(force: true);
				_state.PushToast("Deleted " + ((Object)val).name + ".");
			}
			catch (Exception ex)
			{
				_logger.LogError((object)ex);
				_state.PushToast("Could not delete " + ((Object)val).name + ".");
			}
		}

		public void BeginCopyForge(int instanceId)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ResolveSceneObject(instanceId);
			if ((Object)(object)val == (Object)null)
			{
				RefreshSceneCache(force: true);
				_state.PushToast("That scene object is no longer available.");
				return;
			}
			if (!HasRenderableGeometry(val))
			{
				_state.PushToast(((Object)val).name + " has no visible mesh data to forge from.");
				return;
			}
			if (SemiFunc.IsMultiplayer())
			{
				_state.PushToast("Copy forge creates a local visual clone in multiplayer right now.");
			}
			if (!EnsureFreecamCamera())
			{
				_state.PushToast("Main camera is unavailable for copy forge.");
				return;
			}
			ClearCopyForgeState();
			GameObject val2 = CreateVisualClone(val, preview: true);
			if ((Object)(object)val2 == (Object)null)
			{
				_state.PushToast("Could not build a forge preview for " + ((Object)val).name + ".");
				return;
			}
			_state.SelectedSceneObjectId = 0;
			_copySourceId = instanceId;
			_copySourceName = ((Object)val).name;
			_copyPreview = val2;
			_copyHeightOffset = 0f;
			Quaternion rotation = val.transform.rotation;
			_copyRotationEuler = ((Quaternion)(ref rotation)).eulerAngles;
			_copyDistance = Mathf.Clamp(GetSuggestedDistance(val), 2.2f, 14f);
			_freecamActive = true;
			PositionFreecamForTarget(val);
			_state.Visible = false;
			_state.PushToast("Copy forge armed for " + ((Object)val).name + ".");
		}

		public void Reset()
		{
			ClearCopyForgeState();
			_freecamActive = false;
			RestoreMainCamera();
			SetWorldVisualsVisible(visible: false);
		}

		private void UpdateWorldVisuals()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: 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_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			if (!SectorGame.IsInPlayableRun() || IsCopyForgeActive)
			{
				SetWorldVisualsVisible(visible: false);
				return;
			}
			bool flag = _state.SelectedSceneObjectId != 0;
			if (!(_state.ShowLevelPoints || _state.ShowMeshLabels || _state.ShowMeshBounds || flag))
			{
				SetWorldVisualsVisible(visible: false);
				return;
			}
			EnsureWorldVisualRoot();
			SetWorldVisualsVisible(visible: true);
			int lineIndex = 0;
			int orbIndex = 0;
			if (_state.ShowLevelPoints)
			{
				HashSet<ulong> hashSet = new HashSet<ulong>();
				foreach (LevelPoint item2 in EnumerateLevelPointLabels().Take(48))
				{
					if ((Object)(object)item2 == (Object)null)
					{
						continue;
					}
					AddWorldOrb(ref orbIndex, ((Component)item2).transform.position + Vector3.up * 0.08f, 0.2f);
					foreach (LevelPoint connectedPoint in item2.ConnectedPoints)
					{
						if (!((Object)(object)connectedPoint == (Object)null))
						{
							int instanceID = ((Object)item2).GetInstanceID();
							int instanceID2 = ((Object)connectedPoint).GetInstanceID();
							uint num = (uint)Mathf.Min(instanceID, instanceID2);
							uint num2 = (uint)Mathf.Max(instanceID, instanceID2);
							ulong item = ((ulong)num << 32) | num2;
							if (hashSet.Add(item))
							{
								AddWorldLine(ref lineIndex, ((Component)item2).transform.position + Vector3.up * 0.06f, ((Component)connectedPoint).transform.position + Vector3.up * 0.06f, new Color(0.35f, 0.84f, 1f, 0.92f), 0.045f);
							}
						}
					}
				}
			}
			if (_state.ShowMeshLabels || _state.ShowMeshBounds)
			{
				RefreshSceneCache();
			}
			if (_state.ShowMeshLabels)
			{
				Vector3 start = default(Vector3);
				Vector3 end = default(Vector3);
				foreach (SectorSceneObjectInfo item3 in _sceneObjects.Where((SectorSceneObjectInfo entry) => entry.RendererCount > 0).Take(48))
				{
					GameObject val = ResolveSceneObject(item3.InstanceId);
					if (!((Object)(object)val == (Object)null) && TryGetWorldBounds(val, out var bounds))
					{
						((Vector3)(ref start))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y, ((Bounds)(ref bounds)).center.z);
						((Vector3)(ref end))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z);
						AddWorldLine(ref lineIndex, start, end, new Color(1f, 0.42f, 0.18f, 0.9f), 0.03f);
						Vector3 extents = ((Bounds)(ref bounds)).extents;
						float num3 = Mathf.Clamp(((Vector3)(ref extents)).magnitude * 0.1f, 0.1f, 0.32f);
						AddWorldLine(ref lineIndex, ((Bounds)(ref bounds)).center + Vector3.left * num3, ((Bounds)(ref bounds)).center + Vector3.right * num3, new Color(1f, 0.42f, 0.18f, 0.82f), 0.026f);
						AddWorldLine(ref lineIndex, ((Bounds)(ref bounds)).center + Vector3.forward * num3, ((Bounds)(ref bounds)).center + Vector3.back * num3, new Color(1f, 0.42f, 0.18f, 0.82f), 0.026f);
						AddWorldLine(ref lineIndex, ((Bounds)(ref bounds)).center + Vector3.up * num3, ((Bounds)(ref bounds)).center + Vector3.down * num3, new Color(1f, 0.42f, 0.18f, 0.82f), 0.026f);
					}
				}
			}
			if (_state.ShowMeshBounds)
			{
				foreach (SectorSceneObjectInfo item4 in _sceneObjects.Where((SectorSceneObjectInfo entry) => entry.RendererCount > 0).Take(28))
				{
					GameObject val2 = ResolveSceneObject(item4.InstanceId);
					if ((Object)(object)val2 != (Object)null && TryGetWorldBounds(val2, out var bounds2))
					{
						AddWorldBoundsBox(ref lineIndex, ExpandBounds(bounds2), new Color(1f, 0.34f, 0.19f, 0.88f), 0.024f);
					}
				}
			}
			GameObject val3 = ResolveSceneObject(_state.SelectedSceneObjectId);
			if ((Object)(object)val3 != (Object)null && TryGetWorldBounds(val3, out var bounds3))
			{
				AddWorldBoundsBox(ref lineIndex, ExpandBounds(bounds3), new Color(1f, 0.92f, 0.36f, 0.96f), 0.032f);
			}
			TrimWorldVisualPools(lineIndex, orbIndex);
		}

		private void EnsureWorldVisualRoot()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (!((Object)(object)_worldVisualRoot != (Object)null))
			{
				_worldVisualRoot = new GameObject("Sector.WorldVisuals")
				{
					hideFlags = (HideFlags)61,
					layer = 2
				};
				Object.DontDestroyOnLoad((Object)(object)_worldVisualRoot);
				ApplyRuntimeHideFlags(_worldVisualRoot);
			}
		}

		private void SetWorldVisualsVisible(bool visible)
		{
			if ((Object)(object)_worldVisualRoot != (Object)null)
			{
				_worldVisualRoot.SetActive(visible);
			}
		}

		private void TrimWorldVisualPools(int usedLines, int usedOrbs)
		{
			for (int i = usedLines; i < _worldLinePool.Count; i++)
			{
				if ((Object)(object)_worldLinePool[i] != (Object)null)
				{
					((Component)_worldLinePool[i]).gameObject.SetActive(false);
				}
			}
			for (int j = usedOrbs; j < _worldOrbPool.Count; j++)
			{
				if ((Object)(object)_worldOrbPool[j] != (Object)null)
				{
					_worldOrbPool[j].SetActive(false);
				}
			}
		}

		private void AddWorldOrb(ref int orbIndex, Vector3 position, float scale)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			GameObject orCreateWorldOrb = GetOrCreateWorldOrb(orbIndex++);
			orCreateWorldOrb.transform.position = position;
			orCreateWorldOrb.transform.rotation = Quaternion.identity;
			orCreateWorldOrb.transform.localScale = Vector3.one * scale;
			orCreateWorldOrb.SetActive(true);
		}

		private void AddWorldLine(ref int lineIndex, Vector3 start, Vector3 end, Color color, float width)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			LineRenderer orCreateWorldLine = GetOrCreateWorldLine(lineIndex++);
			((Component)orCreateWorldLine).gameObject.SetActive(true);
			orCreateWorldLine.widthMultiplier = width;
			orCreateWorldLine.startColor = color;
			orCreateWorldLine.endColor = color;
			orCreateWorldLine.positionCount = 2;
			orCreateWorldLine.SetPosition(0, start);
			orCreateWorldLine.SetPosition(1, end);
		}

		private void AddWorldBoundsBox(ref int lineIndex, Bounds bounds, Color color, float width)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_005d: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: 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_016e: 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_0172: Unknown result type (might be due to invalid IL or missing references)
			Vector3 min = ((Bounds)(ref bounds)).min;
			Vector3 max = ((Bounds)(ref bounds)).max;
			Vector3 start = default(Vector3);
			((Vector3)(ref start))..ctor(min.x, min.y, min.z);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(min.x, min.y, max.z);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(min.x, max.y, min.z);
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(min.x, max.y, max.z);
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(max.x, min.y, min.z);
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(max.x, min.y, max.z);
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(max.x, max.y, min.z);
			Vector3 end = default(Vector3);
			((Vector3)(ref end))..ctor(max.x, max.y, max.z);
			AddWorldLine(ref lineIndex, start, val, color, width);
			AddWorldLine(ref lineIndex, start, val2, color, width);
			AddWorldLine(ref lineIndex, start, val4, color, width);
			AddWorldLine(ref lineIndex, val, val3, color, width);
			AddWorldLine(ref lineIndex, val, val5, color, width);
			AddWorldLine(ref lineIndex, val2, val3, color, width);
			AddWorldLine(ref lineIndex, val2, val6, color, width);
			AddWorldLine(ref lineIndex, val4, val5, color, width);
			AddWorldLine(ref lineIndex, val4, val6, color, width);
			AddWorldLine(ref lineIndex, val3, end, color, width);
			AddWorldLine(ref lineIndex, val5, end, color, width);
			AddWorldLine(ref lineIndex, val6, end, color, width);
		}

		private LineRenderer GetOrCreateWorldLine(int index)
		{
			//IL_0025: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			while (_worldLinePool.Count <= index)
			{
				EnsureWorldVisualRoot();
				GameObject val = new GameObject($"SectorLine.{_worldLinePool.Count}")
				{
					hideFlags = (HideFlags)61,
					layer = 2
				};
				val.transform.SetParent(_worldVisualRoot.transform, false);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				((Renderer)val2).sharedMaterial = GetWorldLineMaterial();
				val2.useWorldSpace = true;
				val2.loop = false;
				val2.alignment = (LineAlignment)0;
				val2.textureMode = (LineTextureMode)0;
				val2.numCapVertices = 4;
				val2.numCornerVertices = 4;
				((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val2).receiveShadows = false;
				((Renderer)val2).motionVectorGenerationMode = (MotionVectorGenerationMode)2;
				((Renderer)val2).enabled = true;
				ApplyRuntimeHideFlags(val);
				val.SetActive(false);
				_worldLinePool.Add(val2);
			}
			return _worldLinePool[index];
		}

		private GameObject GetOrCreateWorldOrb(int index)
		{
			while (_worldOrbPool.Count <= index)
			{
				EnsureWorldVisualRoot();
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)val).name = $"SectorLevelPoint.{_worldOrbPool.Count}";
				((Object)val).hideFlags = (HideFlags)61;
				val.layer = 2;
				val.transform.SetParent(_worldVisualRoot.transform, false);
				Collider component = val.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = false;
					Object.Destroy((Object)(object)component);
				}
				MeshRenderer component2 = val.GetComponent<MeshRenderer>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Renderer)component2).sharedMaterial = GetWorldOrbMaterial();
					((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component2).receiveShadows = false;
					((Renderer)component2).lightProbeUsage = (LightProbeUsage)0;
					((Renderer)component2).reflectionProbeUsage = (ReflectionProbeUsage)0;
					((Renderer)component2).motionVectorGenerationMode = (MotionVectorGenerationMode)2;
				}
				ApplyRuntimeHideFlags(val);
				val.SetActive(false);
				_worldOrbPool.Add(val);
			}
			return _worldOrbPool[index];
		}

		private Material GetWorldLineMaterial()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if ((Object)(object)_worldLineMaterial != (Object)null)
			{
				return _worldLineMaterial;
			}
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
			_worldLineMaterial = new Material(val)
			{
				hideFlags = (HideFlags)61
			};
			ApplyRuntimeHideFlags((Object)(object)_worldLineMaterial);
			return _worldLineMaterial;
		}

		private Material GetWorldOrbMaterial()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_worldOrbMaterial != (Object)null)
			{
				return _worldOrbMaterial;
			}
			Shader val = Shader.Find("Standard") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Sprites/Default");
			_worldOrbMaterial = new Material(val)
			{
				hideFlags = (HideFlags)61
			};
			_worldOrbMaterial.color = new Color(0.35f, 0.86f, 1f, 0.96f);
			if (_worldOrbMaterial.HasProperty("_Color"))
			{
				_worldOrbMaterial.SetColor("_Color", new Color(0.35f, 0.86f, 1f, 0.96f));
			}
			if (_worldOrbMaterial.HasProperty("_EmissionColor"))
			{
				_worldOrbMaterial.EnableKeyword("_EMISSION");
				_worldOrbMaterial.SetColor("_EmissionColor", new Color(0.22f, 0.72f, 1f, 1f) * 1.8f);
			}
			ApplyRuntimeHideFlags((Object)(object)_worldOrbMaterial);
			return _worldOrbMaterial;
		}

		private static Bounds ExpandBounds(Bounds bounds)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			((Bounds)(ref bounds)).Expand(Mathf.Max(0.04f, ((Vector3)(ref extents)).magnitude * 0.02f));
			return bounds;
		}

		private void RefreshSceneCache(bool force = false)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (!force && _sceneObjects.Count != 0 && Time.unscaledTime < _nextSceneRefreshTime)
			{
				return;
			}
			_nextSceneRefreshTime = Time.unscaledTime + 0.75f;
			_sceneObjects.Clear();
			_sceneObjectRefs.Clear();
			Transform? cameraTransform = GetCameraTransform();
			Vector3 anchor = ((cameraTransform != null) ? cameraTransform.position : Vector3.zero);
			Transform[] array = Object.FindObjectsByType<Transform>((FindObjectsSortMode)0);
			foreach (Transform val in array)
			{
				GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
				if (!((Object)(object)val2 == (Object)null) && ShouldIncludeObject(val2))
				{
					SectorSceneObjectInfo sectorSceneObjectInfo = BuildSceneInfo(val2);
					_sceneObjects.Add(sectorSceneObjectInfo);
					_sceneObjectRefs[sectorSceneObjectInfo.InstanceId] = new WeakReference<GameObject>(val2);
				}
			}
			_sceneObjects.Sort(delegate(SectorSceneObjectInfo left, SectorSceneObjectInfo right)
			{
				//IL_001c: 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_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid