Decompiled source of Empress Replay System v1.0.1

BepInEx\plugins\Empress-Replays\EmpressReplays.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MenuLib;
using Microsoft.CodeAnalysis;
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("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EmpressReplays")]
[assembly: AssemblyTitle("EmpressReplays")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Empress.REPO.Replays
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.empress.repo.replays", "Empress Replays", "1.0.0")]
	public sealed class EmpressReplaysPlugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Action <>9__23_1;

			public static BuilderDelegate <>9__23_0;

			internal void <RegisterMenu>b__23_0(Transform parent)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Empress Replays", (Action)delegate
				{
					ReplayController.Instance?.OpenBrowserFromMenu();
				}, parent, new Vector2(550f, 56f));
			}

			internal void <RegisterMenu>b__23_1()
			{
				ReplayController.Instance?.OpenBrowserFromMenu();
			}
		}

		public const string PluginGuid = "com.empress.repo.replays";

		public const string PluginName = "Empress Replays";

		public const string PluginVersion = "1.0.0";

		private Harmony _harmony;

		internal static EmpressReplaysPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ReplaySettings Settings { get; private set; }

		internal static string ReplayFolder { get; private set; }

		internal static void DebugLog(string message)
		{
			if (Settings != null && Settings.DebugLogs.Value)
			{
				Log.LogInfo((object)message);
			}
		}

		internal static void DebugWarn(string message)
		{
			if (Settings != null && Settings.DebugLogs.Value)
			{
				Log.LogWarning((object)message);
			}
		}

		private void Awake()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new ReplaySettings(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			ReplayFolder = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty, "Replays");
			Directory.CreateDirectory(ReplayFolder);
			_harmony = new Harmony("com.empress.repo.replays");
			_harmony.PatchAll(typeof(EmpressReplaysPlugin).Assembly);
			ReplayController.EnsureHost();
			RegisterMenu();
			DebugLog("Empress Replays v1.0.0 loaded. Replays in " + ReplayFolder);
		}

		private void RegisterMenu()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			object obj = <>c.<>9__23_0;
			if (obj == null)
			{
				BuilderDelegate val = delegate(Transform parent)
				{
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					MenuAPI.CreateREPOButton("Empress Replays", (Action)delegate
					{
						ReplayController.Instance?.OpenBrowserFromMenu();
					}, parent, new Vector2(550f, 56f));
				};
				<>c.<>9__23_0 = val;
				obj = (object)val;
			}
			MenuAPI.AddElementToMainMenu((BuilderDelegate)obj);
		}
	}
	internal sealed class ReplaySettings
	{
		public readonly ConfigEntry<bool> AutoRecord;

		public readonly ConfigEntry<bool> ShowRecordingIndicator;

		public readonly ConfigEntry<bool> DebugLogs;

		public readonly ConfigEntry<int> MaxReplays;

		public readonly ConfigEntry<float> TickInterval;

		public readonly ConfigEntry<float> CameraSpeed;

		public readonly ConfigEntry<float> LookSensitivity;

		public readonly ConfigEntry<KeyCode> ViewModeKey;

		public readonly ConfigEntry<KeyCode> NextTargetKey;

		public readonly ConfigEntry<KeyCode> ExitKey;

		public ReplaySettings(ConfigFile config)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			AutoRecord = config.Bind<bool>("Recording", "AutoRecord", true, "Automatically record every match and save it on level completion.");
			ShowRecordingIndicator = config.Bind<bool>("Recording", "ShowRecordingIndicator", false, "Show the blinking REC indicator in-game while a match is being recorded.");
			DebugLogs = config.Bind<bool>("Debug", "DebugLogs", false, "Write verbose diagnostic logs to the console (for troubleshooting only).");
			MaxReplays = config.Bind<int>("Recording", "MaxReplays", 100, new ConfigDescription("Maximum saved replays before the oldest is overwritten.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 500), Array.Empty<object>()));
			TickInterval = config.Bind<float>("Recording", "TickInterval", 0.05f, new ConfigDescription("Seconds between recorded snapshots (lower = smoother, bigger files).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.25f), Array.Empty<object>()));
			CameraSpeed = config.Bind<float>("Playback", "CameraSpeed", 8f, new ConfigDescription("Free-camera move speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
			LookSensitivity = config.Bind<float>("Playback", "LookSensitivity", 2.2f, new ConfigDescription("Camera look sensitivity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>()));
			ViewModeKey = config.Bind<KeyCode>("Playback", "ViewModeKey", (KeyCode)118, "Cycles first-person / third-person orbit / free camera.");
			NextTargetKey = config.Bind<KeyCode>("Playback", "NextTargetKey", (KeyCode)9, "Switches which player you are spectating.");
			ExitKey = config.Bind<KeyCode>("Playback", "ExitKey", (KeyCode)27, "Exits playback back to the menu.");
		}
	}
	internal static class ReplayAccess
	{
		private static readonly FieldInfo PlayerAvatarNameField = AccessTools.Field(typeof(PlayerAvatar), "playerName");

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

		private static readonly FieldInfo PlayerAvatarVisualsField = AccessTools.Field(typeof(PlayerAvatar), "playerAvatarVisuals");

		private static readonly FieldInfo PlayerAvatarVisualsMeshParentField = AccessTools.Field(typeof(PlayerAvatarVisuals), "meshParent");

		private static readonly FieldInfo PlayerAvatarVisualsAnimatorField = AccessTools.Field(typeof(PlayerAvatarVisuals), "animator");

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

		private static readonly FieldInfo EnemyParentNameField = AccessTools.Field(typeof(EnemyParent), "enemyName");

		private static readonly FieldInfo EnemyParentEnemyField = AccessTools.Field(typeof(EnemyParent), "Enemy");

		private static readonly FieldInfo EnemyDirectorInstanceField = AccessTools.Field(typeof(EnemyDirector), "instance");

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

		private static readonly FieldInfo EnemyDirectorDifficulty1Field = AccessTools.Field(typeof(EnemyDirector), "enemiesDifficulty1");

		private static readonly FieldInfo EnemyDirectorDifficulty2Field = AccessTools.Field(typeof(EnemyDirector), "enemiesDifficulty2");

		private static readonly FieldInfo EnemyDirectorDifficulty3Field = AccessTools.Field(typeof(EnemyDirector), "enemiesDifficulty3");

		private static readonly FieldInfo EnemyDirectorListField = AccessTools.Field(typeof(EnemyDirector), "enemyList");

		private static readonly FieldInfo EnemyDirectorCurrentListField = AccessTools.Field(typeof(EnemyDirector), "enemyListCurrent");

		private static readonly FieldInfo EnemySetupSpawnObjectsField = AccessTools.Field(typeof(EnemySetup), "spawnObjects");

		private static readonly FieldInfo ValuableDollarField = AccessTools.Field(typeof(ValuableObject), "dollarValueCurrent");

		private static readonly FieldInfo RunManagerLevelCurrentField = AccessTools.Field(typeof(RunManager), "levelCurrent");

		private static readonly FieldInfo GameDirectorCurrentStateField = AccessTools.Field(typeof(GameDirector), "currentState");

		private static readonly FieldInfo GameDirectorPlayerListField = AccessTools.Field(typeof(GameDirector), "PlayerList");

		private static readonly FieldInfo LevelGeneratorGeneratedField = AccessTools.Field(typeof(LevelGenerator), "Generated");

		private static readonly FieldInfo LoadingUiAnimationCompletedField = AccessTools.Field(typeof(LoadingUI), "levelAnimationCompleted");

		private static readonly FieldInfo LevelGeneratorLevelParentField = AccessTools.Field(typeof(LevelGenerator), "LevelParent");

		private static readonly FieldInfo LevelConnectObjectField = AccessTools.Field(typeof(Level), "ConnectObject");

		private static readonly FieldInfo LevelBlockObjectField = AccessTools.Field(typeof(Level), "BlockObject");

		private static readonly FieldInfo LevelStartRoomsField = AccessTools.Field(typeof(Level), "StartRooms");

		private static readonly FieldInfo LevelModulesNormal1Field = AccessTools.Field(typeof(Level), "ModulesNormal1");

		private static readonly FieldInfo LevelModulesNormal2Field = AccessTools.Field(typeof(Level), "ModulesNormal2");

		private static readonly FieldInfo LevelModulesNormal3Field = AccessTools.Field(typeof(Level), "ModulesNormal3");

		private static readonly FieldInfo LevelModulesPassage1Field = AccessTools.Field(typeof(Level), "ModulesPassage1");

		private static readonly FieldInfo LevelModulesPassage2Field = AccessTools.Field(typeof(Level), "ModulesPassage2");

		private static readonly FieldInfo LevelModulesPassage3Field = AccessTools.Field(typeof(Level), "ModulesPassage3");

		private static readonly FieldInfo LevelModulesDeadEnd1Field = AccessTools.Field(typeof(Level), "ModulesDeadEnd1");

		private static readonly FieldInfo LevelModulesDeadEnd2Field = AccessTools.Field(typeof(Level), "ModulesDeadEnd2");

		private static readonly FieldInfo LevelModulesDeadEnd3Field = AccessTools.Field(typeof(Level), "ModulesDeadEnd3");

		private static readonly FieldInfo LevelModulesExtraction1Field = AccessTools.Field(typeof(Level), "ModulesExtraction1");

		private static readonly FieldInfo LevelModulesExtraction2Field = AccessTools.Field(typeof(Level), "ModulesExtraction2");

		private static readonly FieldInfo LevelModulesExtraction3Field = AccessTools.Field(typeof(Level), "ModulesExtraction3");

		private static readonly FieldInfo LevelModulesSpecialField = AccessTools.Field(typeof(Level), "ModulesSpecial");

		private static readonly FieldInfo TruckDoorMeshField = AccessTools.Field(typeof(TruckDoor), "doorMesh");

		private static readonly FieldInfo RunManagerSingleplayerPoolField = AccessTools.Field(typeof(RunManager), "singleplayerPool");

		private static readonly FieldInfo RunManagerMultiplayerPoolField = AccessTools.Field(typeof(RunManager), "multiplayerPool");

		private static readonly FieldInfo MultiplayerPoolResourceCacheField = AccessTools.Field(AccessTools.TypeByName("MultiplayerPool"), "ResourceCache");

		private static readonly FieldInfo RunManagerLevelsField = AccessTools.Field(typeof(RunManager), "levels");

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

		private static readonly FieldInfo RunManagerLevelsCompletedField = AccessTools.Field(typeof(RunManager), "levelsCompleted");

		private static readonly FieldInfo LevelValuablePresetsField = AccessTools.Field(typeof(Level), "ValuablePresets");

		private static readonly FieldInfo LevelValuablesTinyField = AccessTools.Field(typeof(LevelValuables), "tiny");

		private static readonly FieldInfo LevelValuablesSmallField = AccessTools.Field(typeof(LevelValuables), "small");

		private static readonly FieldInfo LevelValuablesMediumField = AccessTools.Field(typeof(LevelValuables), "medium");

		private static readonly FieldInfo LevelValuablesBigField = AccessTools.Field(typeof(LevelValuables), "big");

		private static readonly FieldInfo LevelValuablesWideField = AccessTools.Field(typeof(LevelValuables), "wide");

		private static readonly FieldInfo LevelValuablesTallField = AccessTools.Field(typeof(LevelValuables), "tall");

		private static readonly FieldInfo LevelValuablesVeryTallField = AccessTools.Field(typeof(LevelValuables), "veryTall");

		private static readonly FieldInfo ValuableDirectorTinyValuablesField = AccessTools.Field(typeof(ValuableDirector), "tinyValuables");

		private static readonly FieldInfo ValuableDirectorSmallValuablesField = AccessTools.Field(typeof(ValuableDirector), "smallValuables");

		private static readonly FieldInfo ValuableDirectorMediumValuablesField = AccessTools.Field(typeof(ValuableDirector), "mediumValuables");

		private static readonly FieldInfo ValuableDirectorBigValuablesField = AccessTools.Field(typeof(ValuableDirector), "bigValuables");

		private static readonly FieldInfo ValuableDirectorWideValuablesField = AccessTools.Field(typeof(ValuableDirector), "wideValuables");

		private static readonly FieldInfo ValuableDirectorTallValuablesField = AccessTools.Field(typeof(ValuableDirector), "tallValuables");

		private static readonly FieldInfo ValuableDirectorVeryTallValuablesField = AccessTools.Field(typeof(ValuableDirector), "veryTallValuables");

		private static readonly MethodInfo PrefabRefPrefabNameGetter = AccessTools.PropertyGetter(typeof(PrefabRef), "PrefabName");

		private static readonly MethodInfo PrefabRefResourcePathGetter = AccessTools.PropertyGetter(typeof(PrefabRef), "ResourcePath");

		private static readonly MethodInfo PrefabRefPrefabGetter = AccessTools.PropertyGetter(typeof(PrefabRef), "Prefab");

		private static GameObject[] EnemyResourcePrefabs;

		private static readonly FieldInfo GameDirectorDisableInputField = AccessTools.Field(typeof(GameDirector), "DisableInput");

		private static readonly FieldInfo GameDirectorMainCameraField = AccessTools.Field(typeof(GameDirector), "MainCamera");

		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");

		private static readonly FieldInfo ValuableDirectorListField = AccessTools.Field(typeof(ValuableDirector), "valuableList");

		public static List<PlayerAvatar> GetPlayerList()
		{
			if (GameDirectorPlayerListField != null && (Object)(object)GameDirector.instance != (Object)null)
			{
				return GameDirectorPlayerListField.GetValue(GameDirector.instance) as List<PlayerAvatar>;
			}
			return null;
		}

		public static bool IsGameStateMain()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			if (GameDirectorCurrentStateField == null || (Object)(object)GameDirector.instance == (Object)null)
			{
				return false;
			}
			if (GameDirectorCurrentStateField.GetValue(GameDirector.instance) is gameState val)
			{
				return (int)val == 2;
			}
			return false;
		}

		public static bool IsLevelGenerated()
		{
			if (LevelGeneratorGeneratedField == null || (Object)(object)LevelGenerator.Instance == (Object)null)
			{
				return false;
			}
			object value = LevelGeneratorGeneratedField.GetValue(LevelGenerator.Instance);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static bool IsLoadingComplete()
		{
			if ((Object)(object)LoadingUI.instance == (Object)null)
			{
				return true;
			}
			if (!((Component)LoadingUI.instance).gameObject.activeInHierarchy)
			{
				return true;
			}
			if (LoadingUiAnimationCompletedField == null)
			{
				return true;
			}
			object value = LoadingUiAnimationCompletedField.GetValue(LoadingUI.instance);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static PlayerAvatar GetLocalAvatar()
		{
			if (PlayerControllerAvatarField != null && (Object)(object)PlayerController.instance != (Object)null)
			{
				object? value = PlayerControllerAvatarField.GetValue(PlayerController.instance);
				return (PlayerAvatar)((value is PlayerAvatar) ? value : null);
			}
			return null;
		}

		public static Level GetLevelCurrent()
		{
			if (RunManagerLevelCurrentField != null && (Object)(object)RunManager.instance != (Object)null)
			{
				object? value = RunManagerLevelCurrentField.GetValue(RunManager.instance);
				return (Level)((value is Level) ? value : null);
			}
			return null;
		}

		public static int GetLevelsCompleted()
		{
			if (RunManagerLevelsCompletedField != null && (Object)(object)RunManager.instance != (Object)null)
			{
				object value = RunManagerLevelsCompletedField.GetValue(RunManager.instance);
				if (value is int)
				{
					return (int)value;
				}
				return 0;
			}
			return 0;
		}

		public static void SetLevelCurrent(Level level)
		{
			if (RunManagerLevelCurrentField != null && (Object)(object)RunManager.instance != (Object)null)
			{
				RunManagerLevelCurrentField.SetValue(RunManager.instance, level);
			}
		}

		public static GameObject GetAvatarMeshParent(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null || PlayerAvatarVisualsField == null || PlayerAvatarVisualsMeshParentField == null)
			{
				return null;
			}
			object value = PlayerAvatarVisualsField.GetValue(avatar);
			if (value == null)
			{
				return null;
			}
			object? value2 = PlayerAvatarVisualsMeshParentField.GetValue(value);
			return (GameObject)((value2 is GameObject) ? value2 : null);
		}

		public static GameObject GetAvatarVisualRoot(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null || PlayerAvatarVisualsField == null)
			{
				return null;
			}
			object? value = PlayerAvatarVisualsField.GetValue(avatar);
			Component val = (Component)((value is Component) ? value : null);
			if (!((Object)(object)val != (Object)null))
			{
				return GetAvatarMeshParent(avatar);
			}
			return val.gameObject;
		}

		public static Animator GetAvatarAnimator(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null || PlayerAvatarVisualsField == null || PlayerAvatarVisualsAnimatorField == null)
			{
				return null;
			}
			object value = PlayerAvatarVisualsField.GetValue(avatar);
			if (value == null)
			{
				return null;
			}
			object? value2 = PlayerAvatarVisualsAnimatorField.GetValue(value);
			Animator val = (Animator)((value2 is Animator) ? value2 : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			GameObject avatarVisualRoot = GetAvatarVisualRoot(avatar);
			if (!((Object)(object)avatarVisualRoot != (Object)null))
			{
				return null;
			}
			return avatarVisualRoot.GetComponentInChildren<Animator>(true);
		}

		public static Transform GetTruckDoorMesh(TruckDoor door)
		{
			if ((Object)(object)door == (Object)null || TruckDoorMeshField == null)
			{
				return null;
			}
			object? value = TruckDoorMeshField.GetValue(door);
			return (Transform)((value is Transform) ? value : null);
		}

		public static TruckDoor FindLiveTruckDoor()
		{
			return Object.FindObjectOfType<TruckDoor>();
		}

		public static Animator GetEnemyAnimator(Transform enemyTransform)
		{
			if ((Object)(object)enemyTransform == (Object)null)
			{
				return null;
			}
			Animator[] componentsInChildren = ((Component)enemyTransform).GetComponentsInChildren<Animator>(true);
			foreach (Animator val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.runtimeAnimatorController != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		public static Level FindLevelByName(string resourceName)
		{
			if ((Object)(object)RunManager.instance == (Object)null || RunManagerLevelsField == null || string.IsNullOrEmpty(resourceName))
			{
				return null;
			}
			if (RunManagerLevelsField.GetValue(RunManager.instance) is List<Level> list)
			{
				for (int i = 0; i < list.Count; i++)
				{
					if ((Object)(object)list[i] != (Object)null && ((Object)list[i]).name == resourceName)
					{
						return list[i];
					}
				}
			}
			return null;
		}

		public static void SetDebugLevel(Level level)
		{
			if (RunManagerDebugLevelField != null && (Object)(object)RunManager.instance != (Object)null)
			{
				RunManagerDebugLevelField.SetValue(RunManager.instance, level);
			}
		}

		public static void SetLevelsCompleted(int value)
		{
			if (RunManagerLevelsCompletedField != null && (Object)(object)RunManager.instance != (Object)null)
			{
				RunManagerLevelsCompletedField.SetValue(RunManager.instance, value);
			}
		}

		public static void SetGameInputDisabled(bool value)
		{
			if (GameDirectorDisableInputField != null && (Object)(object)GameDirector.instance != (Object)null)
			{
				GameDirectorDisableInputField.SetValue(GameDirector.instance, value);
			}
		}

		public static Camera GetGameMainCamera()
		{
			if (GameDirectorMainCameraField != null && (Object)(object)GameDirector.instance != (Object)null)
			{
				object? value = GameDirectorMainCameraField.GetValue(GameDirector.instance);
				return (Camera)((value is Camera) ? value : null);
			}
			return null;
		}

		public static Quaternion GetLocalAimRotation()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Camera gameMainCamera = GetGameMainCamera();
			if ((Object)(object)gameMainCamera != (Object)null)
			{
				return ((Component)gameMainCamera).transform.rotation;
			}
			PlayerAvatar localAvatar = GetLocalAvatar();
			if (!((Object)(object)localAvatar != (Object)null))
			{
				return Quaternion.identity;
			}
			return ((Component)localAvatar).transform.rotation;
		}

		public static GameObject LookupPooledModule(string key)
		{
			if (string.IsNullOrEmpty(key) || (Object)(object)RunManager.instance == (Object)null)
			{
				return null;
			}
			if (RunManagerSingleplayerPoolField != null && RunManagerSingleplayerPoolField.GetValue(RunManager.instance) is Dictionary<string, Object> dictionary && dictionary.TryGetValue(key, out var value))
			{
				GameObject val = (GameObject)(object)((value is GameObject) ? value : null);
				if (val != null)
				{
					return val;
				}
			}
			object obj = ((RunManagerMultiplayerPoolField != null) ? RunManagerMultiplayerPoolField.GetValue(RunManager.instance) : null);
			if (obj != null && MultiplayerPoolResourceCacheField != null && MultiplayerPoolResourceCacheField.GetValue(obj) is Dictionary<string, GameObject> dictionary2 && dictionary2.TryGetValue(key, out var value2) && (Object)(object)value2 != (Object)null)
			{
				return value2;
			}
			return null;
		}

		public static GameObject FindPrefabByNameInPool(string rawName)
		{
			if (string.IsNullOrWhiteSpace(rawName) || (Object)(object)RunManager.instance == (Object)null)
			{
				return null;
			}
			string text = NormalizeReplayName(rawName, string.Empty);
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			if (RunManagerSingleplayerPoolField != null && RunManagerSingleplayerPoolField.GetValue(RunManager.instance) is Dictionary<string, Object> dictionary)
			{
				foreach (KeyValuePair<string, Object> item in dictionary)
				{
					Object value = item.Value;
					GameObject val = (GameObject)(object)((value is GameObject) ? value : null);
					if (val != null && NormalizeReplayName(((Object)val).name, string.Empty) == text)
					{
						return val;
					}
				}
			}
			object obj = ((RunManagerMultiplayerPoolField != null) ? RunManagerMultiplayerPoolField.GetValue(RunManager.instance) : null);
			if (obj != null && MultiplayerPoolResourceCacheField != null && MultiplayerPoolResourceCacheField.GetValue(obj) is Dictionary<string, GameObject> dictionary2)
			{
				foreach (KeyValuePair<string, GameObject> item2 in dictionary2)
				{
					if ((Object)(object)item2.Value != (Object)null && NormalizeReplayName(((Object)item2.Value).name, string.Empty) == text)
					{
						return item2.Value;
					}
				}
			}
			return null;
		}

		public static GameObject LookupReplayPrefab(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return null;
			}
			GameObject val = LookupPooledModule(key);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (!key.StartsWith("AssetBundles/"))
			{
				return Resources.Load<GameObject>(key);
			}
			return null;
		}

		public static void SuppressGameCursor()
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (CursorManagerUnlockTimerField != null && (Object)(object)CursorManager.instance != (Object)null)
			{
				CursorManagerUnlockTimerField.SetValue(CursorManager.instance, -1234f);
			}
			if (!((Object)(object)MenuCursor.instance == (Object)null))
			{
				if (MenuCursorShowTimerField != null)
				{
					MenuCursorShowTimerField.SetValue(MenuCursor.instance, 0f);
				}
				if (MenuCursorOverridePosTimerField != null)
				{
					MenuCursorOverridePosTimerField.SetValue(MenuCursor.instance, 0f);
				}
				GameObject val = (GameObject)((MenuCursorMeshField != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val != (Object)null && val.activeSelf)
				{
					val.SetActive(false);
				}
				((Component)MenuCursor.instance).transform.localScale = Vector3.zero;
			}
		}

		public static bool IsAvatarDead(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null || PlayerAvatarDeadSetField == null)
			{
				return false;
			}
			object value = PlayerAvatarDeadSetField.GetValue(avatar);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static string GetPlayerName(PlayerAvatar avatar)
		{
			if ((Object)(object)avatar == (Object)null)
			{
				return "Player";
			}
			string text = ((PlayerAvatarNameField != null) ? (PlayerAvatarNameField.GetValue(avatar) as string) : null);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return "Player";
		}

		public static string GetEnemyName(EnemyParent parent)
		{
			if ((Object)(object)parent == (Object)null)
			{
				return "Monster";
			}
			string text = ((EnemyParentNameField != null) ? (EnemyParentNameField.GetValue(parent) as string) : null);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return "Monster";
		}

		public static Transform GetEnemyTransform(EnemyParent parent)
		{
			if ((Object)(object)parent == (Object)null || EnemyParentEnemyField == null)
			{
				if (!((Object)(object)parent != (Object)null))
				{
					return null;
				}
				return ((Component)parent).transform;
			}
			object? value = EnemyParentEnemyField.GetValue(parent);
			Enemy val = (Enemy)((value is Enemy) ? value : null);
			if (!((Object)(object)val != (Object)null))
			{
				return ((Component)parent).transform;
			}
			return ((Component)val).transform;
		}

		public static GameObject GetEnemyVisualObject(GameObject root)
		{
			return root;
		}

		public static List<EnemyParent> GetSpawnedEnemies()
		{
			EnemyDirector enemyDirector = GetEnemyDirector();
			if ((Object)(object)enemyDirector == (Object)null || EnemyDirectorSpawnedField == null)
			{
				return null;
			}
			return EnemyDirectorSpawnedField.GetValue(enemyDirector) as List<EnemyParent>;
		}

		public static GameObject FindEnemyPrefab(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return null;
			}
			GameObject val = FindEnemyPrefabInDirector(name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (EnemyResourcePrefabs == null)
			{
				EnemyResourcePrefabs = Resources.LoadAll<GameObject>("Enemies");
			}
			string text = NormalizeReplayName(name, "Enemy");
			for (int i = 0; i < EnemyResourcePrefabs.Length; i++)
			{
				GameObject val2 = EnemyResourcePrefabs[i];
				if ((Object)(object)val2 != (Object)null && NormalizeReplayName(((Object)val2).name, "Enemy") == text)
				{
					return val2;
				}
			}
			string text2 = CleanResourceName(name);
			if (!string.IsNullOrEmpty(text2))
			{
				val = Resources.Load<GameObject>("Enemies/" + text2);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				val = Resources.Load<GameObject>("Enemies/Enemy - " + text2);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static GameObject FindEnemyPrefabInDirector(string name)
		{
			EnemyDirector enemyDirector = GetEnemyDirector();
			if ((Object)(object)enemyDirector == (Object)null)
			{
				return null;
			}
			FieldInfo[] array = new FieldInfo[5] { EnemyDirectorCurrentListField, EnemyDirectorListField, EnemyDirectorDifficulty1Field, EnemyDirectorDifficulty2Field, EnemyDirectorDifficulty3Field };
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = FindEnemyPrefabInSetups((array[i] != null) ? (array[i].GetValue(enemyDirector) as List<EnemySetup>) : null, name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static EnemyDirector GetEnemyDirector()
		{
			if (!(EnemyDirectorInstanceField != null))
			{
				return null;
			}
			object? value = EnemyDirectorInstanceField.GetValue(null);
			return (EnemyDirector)((value is EnemyDirector) ? value : null);
		}

		private static GameObject FindEnemyPrefabInSetups(List<EnemySetup> setups, string name)
		{
			if (setups == null)
			{
				return null;
			}
			string text = NormalizeReplayName(name, "Enemy");
			for (int i = 0; i < setups.Count; i++)
			{
				EnemySetup val = setups[i];
				if (!((Object)(object)val == (Object)null))
				{
					if (NormalizeReplayName(((Object)val).name, "Enemy") == text)
					{
						return FindFirstEnemyPrefab(val);
					}
					GameObject val2 = FindPrefabRefPrefabInList((EnemySetupSpawnObjectsField != null) ? (EnemySetupSpawnObjectsField.GetValue(val) as List<PrefabRef>) : null, text, "Enemy");
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
			}
			return null;
		}

		private static GameObject FindFirstEnemyPrefab(EnemySetup setup)
		{
			if ((Object)(object)setup == (Object)null || EnemySetupSpawnObjectsField == null)
			{
				return null;
			}
			if (!(EnemySetupSpawnObjectsField.GetValue(setup) is List<PrefabRef> list))
			{
				return null;
			}
			for (int i = 0; i < list.Count; i++)
			{
				GameObject prefabRefPrefab = GetPrefabRefPrefab(list[i]);
				if ((Object)(object)prefabRefPrefab != (Object)null)
				{
					return prefabRefPrefab;
				}
			}
			return null;
		}

		public static float GetValuableValue(ValuableObject valuable)
		{
			if ((Object)(object)valuable == (Object)null || ValuableDollarField == null)
			{
				return 0f;
			}
			object value = ValuableDollarField.GetValue(valuable);
			if (value is float)
			{
				return (float)value;
			}
			return 0f;
		}

		public static GameObject GetLevelParentObject()
		{
			if ((Object)(object)LevelGenerator.Instance == (Object)null || LevelGeneratorLevelParentField == null)
			{
				return null;
			}
			object? value = LevelGeneratorLevelParentField.GetValue(LevelGenerator.Instance);
			return (GameObject)((value is GameObject) ? value : null);
		}

		public static void CaptureGeneratedModules(List<ReplayModule> modules)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			if (modules == null)
			{
				return;
			}
			modules.Clear();
			GameObject levelParentObject = GetLevelParentObject();
			if ((Object)(object)levelParentObject == (Object)null)
			{
				return;
			}
			Level levelCurrent = GetLevelCurrent();
			Dictionary<string, string> dictionary = (((Object)(object)levelCurrent != (Object)null) ? BuildLevelPrefabPathMap(levelCurrent) : new Dictionary<string, string>());
			Transform transform = levelParentObject.transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				if (!((Object)(object)child == (Object)null) && IsModuleChild(child))
				{
					string prefabName = CleanResourceName(((Object)child).name);
					string key = NormalizeReplayName(((Object)child).name, string.Empty);
					string value;
					string resourcePath = (dictionary.TryGetValue(key, out value) ? value : string.Empty);
					ReplayModule replayModule = new ReplayModule
					{
						ResourcePath = resourcePath,
						PrefabName = prefabName,
						Position = child.position,
						Rotation = child.rotation
					};
					CaptureRendererStates(child, replayModule);
					modules.Add(replayModule);
				}
			}
		}

		private static void CaptureRendererStates(Transform child, ReplayModule module)
		{
			Renderer[] componentsInChildren = ((Component)child).GetComponentsInChildren<Renderer>(true);
			bool[] array = new bool[componentsInChildren.Length];
			int[] array2 = new int[componentsInChildren.Length];
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Renderer val = componentsInChildren[i];
				array[i] = (Object)(object)val != (Object)null && val.enabled && ((Component)val).gameObject.activeInHierarchy;
				array2[i] = (((Object)(object)val != (Object)null) ? RendererPathHash(child, ((Component)val).transform) : 0);
			}
			module.RendererStates = array;
			module.RendererPathHashes = array2;
		}

		public static int RendererPathHash(Transform root, Transform target)
		{
			StringBuilder stringBuilder = new StringBuilder();
			Transform val = target;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				stringBuilder.Insert(0, ((Object)val).name);
				stringBuilder.Insert(0, '/');
				val = val.parent;
			}
			return Animator.StringToHash(stringBuilder.ToString());
		}

		private static bool IsModuleChild(Transform child)
		{
			if (!((Object)(object)((Component)child).GetComponent<Module>() != (Object)null) && !((Object)(object)((Component)child).GetComponent<StartRoom>() != (Object)null) && !((Object)(object)((Component)child).GetComponent<ModuleConnectObject>() != (Object)null) && !((Object)(object)((Component)child).GetComponent<ModuleBlockObject>() != (Object)null))
			{
				return (Object)(object)((Component)child).GetComponentInChildren<Renderer>(true) != (Object)null;
			}
			return true;
		}

		public static GameObject ResolveModulePrefab(string resourcePath, string prefabName, Dictionary<string, GameObject> levelPrefabs)
		{
			if (levelPrefabs != null && !string.IsNullOrEmpty(prefabName))
			{
				string text = NormalizeReplayName(prefabName, string.Empty);
				if (!string.IsNullOrEmpty(text) && levelPrefabs.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
				{
					return value;
				}
			}
			GameObject val = LookupReplayPrefab(resourcePath);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = FindPrefabByNameInPool(prefabName);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return FindPrefabByNameInPool(resourcePath);
		}

		public static Dictionary<string, GameObject> BuildLevelPrefabObjectMap(Level level)
		{
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
			if ((Object)(object)level == (Object)null)
			{
				return dictionary;
			}
			AddPrefabObjectField(dictionary, level, LevelConnectObjectField);
			AddPrefabObjectField(dictionary, level, LevelBlockObjectField);
			AddPrefabObjectListField(dictionary, level, LevelStartRoomsField);
			AddPrefabObjectListField(dictionary, level, LevelModulesNormal1Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesNormal2Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesNormal3Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesPassage1Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesPassage2Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesPassage3Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesDeadEnd1Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesDeadEnd2Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesDeadEnd3Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesExtraction1Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesExtraction2Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesExtraction3Field);
			AddPrefabObjectListField(dictionary, level, LevelModulesSpecialField);
			return dictionary;
		}

		private static void AddPrefabObjectField(Dictionary<string, GameObject> map, object owner, FieldInfo field)
		{
			if (map != null && owner != null && !(field == null))
			{
				object? value = field.GetValue(owner);
				AddPrefabObject(map, (PrefabRef)((value is PrefabRef) ? value : null));
			}
		}

		private static void AddPrefabObjectListField(Dictionary<string, GameObject> map, object owner, FieldInfo field)
		{
			if (map != null && owner != null && !(field == null) && field.GetValue(owner) is List<PrefabRef> list)
			{
				for (int i = 0; i < list.Count; i++)
				{
					AddPrefabObject(map, list[i]);
				}
			}
		}

		private static void AddPrefabObject(Dictionary<string, GameObject> map, PrefabRef prefabRef)
		{
			if (map == null || prefabRef == null)
			{
				return;
			}
			GameObject prefabRefPrefab = GetPrefabRefPrefab(prefabRef);
			if (!((Object)(object)prefabRefPrefab == (Object)null))
			{
				string prefabRefString = GetPrefabRefString(PrefabRefPrefabNameGetter, prefabRef);
				string text = NormalizeReplayName(string.IsNullOrEmpty(prefabRefString) ? ((Object)prefabRefPrefab).name : prefabRefString, string.Empty);
				if (!string.IsNullOrEmpty(text) && !map.ContainsKey(text))
				{
					map.Add(text, prefabRefPrefab);
				}
			}
		}

		private static Dictionary<string, string> BuildLevelPrefabPathMap(Level level)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			AddPrefabRefField(dictionary, level, LevelConnectObjectField);
			AddPrefabRefField(dictionary, level, LevelBlockObjectField);
			AddPrefabRefListField(dictionary, level, LevelStartRoomsField);
			AddPrefabRefListField(dictionary, level, LevelModulesNormal1Field);
			AddPrefabRefListField(dictionary, level, LevelModulesNormal2Field);
			AddPrefabRefListField(dictionary, level, LevelModulesNormal3Field);
			AddPrefabRefListField(dictionary, level, LevelModulesPassage1Field);
			AddPrefabRefListField(dictionary, level, LevelModulesPassage2Field);
			AddPrefabRefListField(dictionary, level, LevelModulesPassage3Field);
			AddPrefabRefListField(dictionary, level, LevelModulesDeadEnd1Field);
			AddPrefabRefListField(dictionary, level, LevelModulesDeadEnd2Field);
			AddPrefabRefListField(dictionary, level, LevelModulesDeadEnd3Field);
			AddPrefabRefListField(dictionary, level, LevelModulesExtraction1Field);
			AddPrefabRefListField(dictionary, level, LevelModulesExtraction2Field);
			AddPrefabRefListField(dictionary, level, LevelModulesExtraction3Field);
			AddPrefabRefListField(dictionary, level, LevelModulesSpecialField);
			return dictionary;
		}

		private static void AddPrefabRefField(Dictionary<string, string> map, object owner, FieldInfo field)
		{
			if (map != null && owner != null && !(field == null))
			{
				object? value = field.GetValue(owner);
				AddPrefabRef(map, (PrefabRef)((value is PrefabRef) ? value : null));
			}
		}

		private static void AddPrefabRefListField(Dictionary<string, string> map, object owner, FieldInfo field)
		{
			if (map != null && owner != null && !(field == null) && field.GetValue(owner) is List<PrefabRef> list)
			{
				for (int i = 0; i < list.Count; i++)
				{
					AddPrefabRef(map, list[i]);
				}
			}
		}

		private static void AddPrefabRef(Dictionary<string, string> map, PrefabRef prefabRef)
		{
			if (map == null || prefabRef == null)
			{
				return;
			}
			string prefabRefString = GetPrefabRefString(PrefabRefPrefabNameGetter, prefabRef);
			string prefabResourcePath = GetPrefabResourcePath(prefabRef);
			if (!string.IsNullOrEmpty(prefabRefString) && !string.IsNullOrEmpty(prefabResourcePath))
			{
				string key = NormalizeReplayName(prefabRefString, string.Empty);
				if (!map.ContainsKey(key))
				{
					map.Add(key, prefabResourcePath);
				}
			}
		}

		public static string GetPrefabResourcePath(PrefabRef prefabRef)
		{
			return GetPrefabRefString(PrefabRefResourcePathGetter, prefabRef);
		}

		public static GameObject FindValuablePrefab(string cleanedName)
		{
			if (string.IsNullOrEmpty(cleanedName))
			{
				return null;
			}
			GameObject val = FindValuablePrefabInLevel(GetLevelCurrent(), cleanedName);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = FindValuablePrefabInDirector(cleanedName);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (RunManagerLevelsField != null && (Object)(object)RunManager.instance != (Object)null && RunManagerLevelsField.GetValue(RunManager.instance) is List<Level> list)
			{
				for (int i = 0; i < list.Count; i++)
				{
					val = FindValuablePrefabInLevel(list[i], cleanedName);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			if (ValuableDirectorListField == null || (Object)(object)ValuableDirector.instance == (Object)null)
			{
				return null;
			}
			if (!(ValuableDirectorListField.GetValue(ValuableDirector.instance) is IEnumerable enumerable))
			{
				return null;
			}
			foreach (object item in enumerable)
			{
				ValuableObject val2 = (ValuableObject)((item is ValuableObject) ? item : null);
				if (!((Object)(object)val2 == (Object)null) && ((Object)val2).name.Replace("(Clone)", string.Empty).Replace("Valuable ", string.Empty).Trim() == cleanedName)
				{
					return ((Component)val2).gameObject;
				}
			}
			return null;
		}

		private static GameObject FindValuablePrefabInLevel(Level level, string cleanedName)
		{
			if ((Object)(object)level == (Object)null || LevelValuablePresetsField == null)
			{
				return null;
			}
			if (!(LevelValuablePresetsField.GetValue(level) is List<LevelValuables> list))
			{
				return null;
			}
			for (int i = 0; i < list.Count; i++)
			{
				GameObject val = FindValuablePrefabInPreset(list[i], cleanedName);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static GameObject FindValuablePrefabInPreset(LevelValuables preset, string cleanedName)
		{
			if ((Object)(object)preset == (Object)null)
			{
				return null;
			}
			FieldInfo[] array = new FieldInfo[7] { LevelValuablesTinyField, LevelValuablesSmallField, LevelValuablesMediumField, LevelValuablesBigField, LevelValuablesWideField, LevelValuablesTallField, LevelValuablesVeryTallField };
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = FindValuablePrefabInList((array[i] != null) ? (array[i].GetValue(preset) as List<PrefabRef>) : null, cleanedName);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static GameObject FindValuablePrefabInDirector(string cleanedName)
		{
			if ((Object)(object)ValuableDirector.instance == (Object)null)
			{
				return null;
			}
			FieldInfo[] array = new FieldInfo[7] { ValuableDirectorTinyValuablesField, ValuableDirectorSmallValuablesField, ValuableDirectorMediumValuablesField, ValuableDirectorBigValuablesField, ValuableDirectorWideValuablesField, ValuableDirectorTallValuablesField, ValuableDirectorVeryTallValuablesField };
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = FindValuablePrefabInList((array[i] != null) ? (array[i].GetValue(ValuableDirector.instance) as List<PrefabRef>) : null, cleanedName);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static GameObject FindValuablePrefabInList(List<PrefabRef> prefabs, string cleanedName)
		{
			if (prefabs == null || prefabs.Count == 0)
			{
				return null;
			}
			string target = NormalizeValuableName(cleanedName);
			return FindPrefabRefPrefabInList(prefabs, target, "Valuable");
		}

		private static bool PrefabRefMatches(PrefabRef prefabRef, string target)
		{
			return PrefabRefMatches(prefabRef, target, "Valuable");
		}

		private static GameObject FindPrefabRefPrefabInList(List<PrefabRef> prefabs, string target, string prefix)
		{
			if (prefabs == null || prefabs.Count == 0)
			{
				return null;
			}
			for (int i = 0; i < prefabs.Count; i++)
			{
				PrefabRef val = prefabs[i];
				if (val != null && PrefabRefMatches(val, target, prefix))
				{
					GameObject prefabRefPrefab = GetPrefabRefPrefab(val);
					if ((Object)(object)prefabRefPrefab != (Object)null)
					{
						return prefabRefPrefab;
					}
				}
			}
			return null;
		}

		private static bool PrefabRefMatches(PrefabRef prefabRef, string target, string prefix)
		{
			if (string.IsNullOrEmpty(target))
			{
				return false;
			}
			if (NormalizeReplayName(GetPrefabRefString(PrefabRefPrefabNameGetter, prefabRef), prefix) == target)
			{
				return true;
			}
			return NormalizeReplayName(GetPrefabRefString(PrefabRefResourcePathGetter, prefabRef), prefix) == target;
		}

		private static string GetPrefabRefString(MethodInfo getter, PrefabRef prefabRef)
		{
			if (getter == null || prefabRef == null)
			{
				return string.Empty;
			}
			try
			{
				return (getter.Invoke(prefabRef, null) as string) ?? string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		private static GameObject GetPrefabRefPrefab(PrefabRef prefabRef)
		{
			if (PrefabRefPrefabGetter == null || prefabRef == null)
			{
				return null;
			}
			try
			{
				object? obj = PrefabRefPrefabGetter.Invoke(prefabRef, null);
				return (GameObject)((obj is GameObject) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		private static string NormalizeValuableName(string raw)
		{
			return NormalizeReplayName(raw, "Valuable");
		}

		private static string NormalizeReplayName(string raw, string prefix)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return string.Empty;
			}
			string text = CleanResourceName(raw);
			text = text.Replace("(Clone)", string.Empty).Trim();
			if (!string.IsNullOrWhiteSpace(prefix))
			{
				text = text.Replace(prefix + " ", string.Empty).Replace(prefix + "_", string.Empty).Replace(prefix + "-", string.Empty)
					.Trim();
			}
			text = text.Replace(" ", string.Empty).Replace("_", string.Empty).Replace("-", string.Empty);
			return text.ToLowerInvariant();
		}

		private static string CleanResourceName(string raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return string.Empty;
			}
			string text = raw.Replace("\\", "/");
			int num = text.LastIndexOf('/');
			if (num >= 0 && num + 1 < text.Length)
			{
				text = text.Substring(num + 1);
			}
			int num2 = text.LastIndexOf('.');
			if (num2 > 0)
			{
				text = text.Substring(0, num2);
			}
			return text.Replace("(Clone)", string.Empty).Trim();
		}
	}
	internal enum ReplayAnimParamType : byte
	{
		Float,
		Int,
		Bool,
		Trigger
	}
	internal sealed class ReplayAnimParam
	{
		public string Name = string.Empty;

		public ReplayAnimParamType Type;

		public int Hash;
	}
	internal sealed class ReplayAnimBinding
	{
		public Animator Animator;

		public HashSet<int> ParamHashes;

		public bool DrivesSchema;
	}
	internal static class ReplayAnimation
	{
		private const float FloatEpsilon = 0.01f;

		private const float SpeedEpsilon = 0.02f;

		public static ReplayAnimParam[] BuildSchema(Animator animator)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)animator == (Object)null || (Object)(object)animator.runtimeAnimatorController == (Object)null)
			{
				return null;
			}
			AnimatorControllerParameter[] parameters;
			try
			{
				parameters = animator.parameters;
			}
			catch
			{
				return null;
			}
			if (parameters == null || parameters.Length == 0)
			{
				return null;
			}
			ReplayAnimParam[] array = new ReplayAnimParam[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				AnimatorControllerParameter val = parameters[i];
				array[i] = new ReplayAnimParam
				{
					Name = val.name,
					Type = MapType(val.type),
					Hash = val.nameHash
				};
			}
			return array;
		}

		public static float Snapshot(Animator animator, ReplayAnimParam[] schema, float[] destination)
		{
			if ((Object)(object)animator == (Object)null || schema == null || destination == null)
			{
				return 1f;
			}
			for (int i = 0; i < schema.Length && i < destination.Length; i++)
			{
				ReplayAnimParam replayAnimParam = schema[i];
				switch (replayAnimParam.Type)
				{
				case ReplayAnimParamType.Float:
					destination[i] = animator.GetFloat(replayAnimParam.Hash);
					break;
				case ReplayAnimParamType.Int:
					destination[i] = animator.GetInteger(replayAnimParam.Hash);
					break;
				default:
					destination[i] = (animator.GetBool(replayAnimParam.Hash) ? 1f : 0f);
					break;
				}
			}
			return animator.speed;
		}

		public static bool Changed(ReplayAnimParam[] schema, float[] current, float[] last, float currentSpeed, float lastSpeed)
		{
			if (schema == null || current == null || last == null)
			{
				return false;
			}
			if (Mathf.Abs(currentSpeed - lastSpeed) > 0.02f)
			{
				return true;
			}
			for (int i = 0; i < schema.Length && i < current.Length && i < last.Length; i++)
			{
				if (schema[i].Type == ReplayAnimParamType.Float)
				{
					if (Mathf.Abs(current[i] - last[i]) > 0.01f)
					{
						return true;
					}
				}
				else if (!Mathf.Approximately(current[i], last[i]))
				{
					return true;
				}
			}
			return false;
		}

		public static ReplayAnimBinding[] BuildBindings(Animator[] animators, ReplayAnimParam[] schema)
		{
			if (animators == null || animators.Length == 0 || schema == null || schema.Length == 0)
			{
				return null;
			}
			List<ReplayAnimBinding> list = new List<ReplayAnimBinding>();
			foreach (Animator val in animators)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.runtimeAnimatorController == (Object)null)
				{
					continue;
				}
				AnimatorControllerParameter[] parameters;
				try
				{
					parameters = val.parameters;
				}
				catch
				{
					continue;
				}
				if (parameters == null || parameters.Length == 0)
				{
					continue;
				}
				HashSet<int> hashSet = new HashSet<int>();
				for (int j = 0; j < parameters.Length; j++)
				{
					hashSet.Add(parameters[j].nameHash);
				}
				bool flag = false;
				for (int k = 0; k < schema.Length; k++)
				{
					if (hashSet.Contains(schema[k].Hash))
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					list.Add(new ReplayAnimBinding
					{
						Animator = val,
						ParamHashes = hashSet,
						DrivesSchema = true
					});
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list.ToArray();
		}

		public static void Apply(ReplayAnimBinding[] bindings, ReplayAnimParam[] schema, float[] values, float speed, float[] triggerState)
		{
			if (bindings == null || schema == null || values == null)
			{
				return;
			}
			foreach (ReplayAnimBinding replayAnimBinding in bindings)
			{
				if (replayAnimBinding == null || (Object)(object)replayAnimBinding.Animator == (Object)null)
				{
					continue;
				}
				for (int j = 0; j < schema.Length && j < values.Length; j++)
				{
					ReplayAnimParam replayAnimParam = schema[j];
					if (!replayAnimBinding.ParamHashes.Contains(replayAnimParam.Hash))
					{
						continue;
					}
					switch (replayAnimParam.Type)
					{
					case ReplayAnimParamType.Float:
						replayAnimBinding.Animator.SetFloat(replayAnimParam.Hash, values[j]);
						break;
					case ReplayAnimParamType.Int:
						replayAnimBinding.Animator.SetInteger(replayAnimParam.Hash, Mathf.RoundToInt(values[j]));
						break;
					case ReplayAnimParamType.Bool:
						replayAnimBinding.Animator.SetBool(replayAnimParam.Hash, values[j] >= 0.5f);
						break;
					case ReplayAnimParamType.Trigger:
						if (triggerState != null && j < triggerState.Length && values[j] >= 0.5f && triggerState[j] < 0.5f)
						{
							replayAnimBinding.Animator.SetTrigger(replayAnimParam.Hash);
						}
						break;
					}
				}
				if (replayAnimBinding.DrivesSchema)
				{
					replayAnimBinding.Animator.speed = speed;
				}
			}
			if (triggerState == null)
			{
				return;
			}
			for (int k = 0; k < schema.Length && k < values.Length && k < triggerState.Length; k++)
			{
				if (schema[k].Type == ReplayAnimParamType.Trigger)
				{
					triggerState[k] = values[k];
				}
			}
		}

		private static ReplayAnimParamType MapType(AnimatorControllerParameterType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			if ((int)type != 1)
			{
				if ((int)type != 3)
				{
					if ((int)type == 9)
					{
						return ReplayAnimParamType.Trigger;
					}
					return ReplayAnimParamType.Bool;
				}
				return ReplayAnimParamType.Int;
			}
			return ReplayAnimParamType.Float;
		}
	}
	internal enum ReplayViewMode
	{
		FirstPerson,
		ThirdPerson,
		Free
	}
	internal sealed class ReplayCamera
	{
		private float _yaw;

		private float _pitch;

		private float _orbitDistance = 4.5f;

		private bool _active;

		private Vector3 _position;

		private Quaternion _rotation = Quaternion.identity;

		private bool _followAimValid;

		private Quaternion _followAim = Quaternion.identity;

		public bool Active => _active;

		public ReplayViewMode Mode { get; private set; } = ReplayViewMode.ThirdPerson;

		public Transform FollowTarget { get; set; }

		public Vector3 Position => _position;

		public Quaternion Rotation => _rotation;

		public void Begin(Vector3 startPosition, Quaternion startRotation)
		{
			//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)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			_position = startPosition;
			_rotation = startRotation;
			Vector3 eulerAngles = ((Quaternion)(ref startRotation)).eulerAngles;
			_pitch = ((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x);
			_yaw = eulerAngles.y;
			_active = true;
		}

		public void End()
		{
			_active = false;
		}

		public void SetMode(ReplayViewMode mode)
		{
			Mode = mode;
		}

		public void CycleMode()
		{
			Mode = (ReplayViewMode)((int)(Mode + 1) % 3);
		}

		public void SetFollowAim(bool valid, Quaternion aim)
		{
			//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)
			_followAimValid = valid;
			_followAim = aim;
		}

		public void Tick(float deltaTime, bool lookEnabled)
		{
			if (_active)
			{
				float value = EmpressReplaysPlugin.Settings.LookSensitivity.Value;
				if ((Mode == ReplayViewMode.Free || Mode == ReplayViewMode.ThirdPerson) && lookEnabled)
				{
					_yaw += Input.GetAxisRaw("Mouse X") * value;
					_pitch -= Input.GetAxisRaw("Mouse Y") * value;
					_pitch = Mathf.Clamp(_pitch, -85f, 85f);
				}
				float axis = Input.GetAxis("Mouse ScrollWheel");
				if (Mathf.Abs(axis) > 0.0001f && Mode == ReplayViewMode.ThirdPerson)
				{
					_orbitDistance = Mathf.Clamp(_orbitDistance - axis * 4f, 1.5f, 12f);
				}
				switch (Mode)
				{
				case ReplayViewMode.FirstPerson:
					TickFirstPerson();
					break;
				case ReplayViewMode.ThirdPerson:
					TickThirdPerson();
					break;
				default:
					TickFree(deltaTime);
					break;
				}
			}
		}

		private void TickFirstPerson()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)FollowTarget == (Object)null)
			{
				SetMode(ReplayViewMode.Free);
				return;
			}
			Quaternion rotation = (_followAimValid ? _followAim : FollowTarget.rotation);
			_position = FollowTarget.position + Vector3.up * 1.6f;
			_rotation = rotation;
			Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles;
			_pitch = ((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x);
			_yaw = eulerAngles.y;
		}

		private void TickThirdPerson()
		{
			//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)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_00a8: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)FollowTarget == (Object)null)
			{
				SetMode(ReplayViewMode.Free);
				return;
			}
			Quaternion val = Quaternion.Euler(_pitch, _yaw, 0f);
			Vector3 val2 = FollowTarget.position + Vector3.up * 1.4f;
			Vector3 val3 = val2 - val * Vector3.forward * _orbitDistance;
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Linecast(val2, val3, ref val4, -1, (QueryTriggerInteraction)1) && (Object)(object)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<PlayerAvatar>() == (Object)null)
			{
				val3 = ((RaycastHit)(ref val4)).point + ((RaycastHit)(ref val4)).normal * 0.3f;
			}
			_position = val3;
			_rotation = val;
		}

		private void TickFree(float deltaTime)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = (_rotation = Quaternion.Euler(_pitch, _yaw, 0f));
			float num = EmpressReplaysPlugin.Settings.CameraSpeed.Value;
			if (Input.GetKey((KeyCode)304))
			{
				num *= 3f;
			}
			Vector3 val2 = Vector3.zero;
			if (Input.GetKey((KeyCode)119))
			{
				val2 += val * Vector3.forward;
			}
			if (Input.GetKey((KeyCode)115))
			{
				val2 += val * Vector3.back;
			}
			if (Input.GetKey((KeyCode)100))
			{
				val2 += val * Vector3.right;
			}
			if (Input.GetKey((KeyCode)97))
			{
				val2 += val * Vector3.left;
			}
			if (Input.GetKey((KeyCode)101))
			{
				val2 += Vector3.up;
			}
			if (Input.GetKey((KeyCode)113))
			{
				val2 += Vector3.down;
			}
			_position += val2 * num * deltaTime;
		}
	}
	internal enum ReplayMode
	{
		Idle,
		Recording,
		Playback
	}
	internal sealed class ReplayController : MonoBehaviour
	{
		private readonly ReplayRecorder _recorder = new ReplayRecorder();

		private readonly ReplayPlayer _player = new ReplayPlayer();

		private readonly ReplayCamera _camera = new ReplayCamera();

		private readonly ReplayLevelOverlay _levelOverlay = new ReplayLevelOverlay();

		private ReplayHud _hud;

		private ReplayMode _mode;

		private int _sceneHandle = -1;

		private bool _levelRecorded;

		private List<ReplayGhost> _playerTargets = new List<ReplayGhost>();

		private int _targetIndex;

		private ReplayData _pendingReplay;

		private bool _awaitingPlaybackLevel;

		private bool _settling;

		private float _settleTimer;

		private float _rehideTimer;

		private bool _suppressRecording;

		private const float PlaybackSettleSeconds = 3.5f;

		public static ReplayController Instance { get; private set; }

		public static bool IsPlaybackBoot { get; private set; }

		public ReplayMode Mode => _mode;

		public ReplayPlayer Player => _player;

		public ReplayCamera Camera => _camera;

		public static ReplayController EnsureHost()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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: Expected O, but got Unknown
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			GameObject val = new GameObject("Empress Replay Controller");
			val.transform.parent = null;
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)val);
			Instance = val.AddComponent<ReplayController>();
			return Instance;
		}

		private void Awake()
		{
			Instance = this;
			_hud = ReplayHud.Create(this);
		}

		private void Update()
		{
			HandleSceneChange();
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			if (_awaitingPlaybackLevel)
			{
				if (_pendingReplay != null && LevelFullyLoaded())
				{
					if (!_settling)
					{
						_settling = true;
						_settleTimer = 3.5f;
						_hud.Toast("Level loaded, starting replay", 3.5f);
					}
					else
					{
						_settleTimer -= unscaledDeltaTime;
						if (_settleTimer <= 0f)
						{
							BeginPlaybackInLevel();
						}
					}
				}
				_hud.UpdateState(_mode, _recorder.FrameCount, _player, _camera);
				return;
			}
			if (_mode == ReplayMode.Idle && !_levelRecorded && !_suppressRecording && EmpressReplaysPlugin.Settings.AutoRecord.Value && InLevel() && ReplayAccess.IsLevelGenerated())
			{
				_levelRecorded = true;
				_recorder.Begin();
				_mode = ReplayMode.Recording;
				_hud.Toast("● Recording match", 2.5f);
				EmpressReplaysPlugin.DebugLog("Empress Replays recording started for " + ReplayLayoutCapture.LevelName);
			}
			if (_mode == ReplayMode.Recording)
			{
				_recorder.Tick(Time.deltaTime);
			}
			if (_mode == ReplayMode.Playback)
			{
				if (Time.timeScale != 0f)
				{
					Time.timeScale = 0f;
				}
				ReplayEnvironment.Apply();
				_player.Tick(unscaledDeltaTime);
				UpdateDeathFollow();
				PushFollowAim();
				ApplyFirstPersonHiding();
				bool mouseButton = Input.GetMouseButton(1);
				_camera.Tick(unscaledDeltaTime, mouseButton);
				HandlePlaybackInput();
				_rehideTimer -= unscaledDeltaTime;
				if (_rehideTimer <= 0f)
				{
					_rehideTimer = 1f;
					ReplayLiveSuppressor.RefreshHidden();
				}
			}
			_hud.UpdateState(_mode, _recorder.FrameCount, _player, _camera);
		}

		private void LateUpdate()
		{
			if (_hud.WantsCursor() && (_mode != ReplayMode.Playback || !Input.GetMouseButton(1)))
			{
				ReplayAccess.SuppressGameCursor();
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		public void OnLevelGenerateStarting()
		{
			if (_mode == ReplayMode.Recording)
			{
				ReplayData data = _recorder.End();
				_mode = ReplayMode.Idle;
				SaveReplay(data);
			}
			_levelRecorded = false;
			if (!IsPlaybackBoot)
			{
				_suppressRecording = false;
			}
		}

		public void OnLevelChanging(bool completed)
		{
			if (_mode == ReplayMode.Recording)
			{
				ReplayData data = _recorder.End();
				_mode = ReplayMode.Idle;
				SaveReplay(data);
			}
		}

		private void SaveReplay(ReplayData data)
		{
			if (data == null || data.FrameCount < 4)
			{
				return;
			}
			try
			{
				string path = SafeName(data.LevelName) + "_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".emrly";
				string text = Path.Combine(EmpressReplaysPlugin.ReplayFolder, path);
				ReplayFormat.Save(text, data);
				EnforceReplayCap();
				_hud.Toast("Replay saved", 3f);
				EmpressReplaysPlugin.DebugLog("Saved replay: " + text);
			}
			catch (Exception ex)
			{
				EmpressReplaysPlugin.Log.LogError((object)("Replay save failed: " + ex));
			}
		}

		private void EnforceReplayCap()
		{
			int value = EmpressReplaysPlugin.Settings.MaxReplays.Value;
			List<string> list = ListReplays();
			if (list.Count <= value)
			{
				return;
			}
			list.Sort(CompareByWriteTimeAsc);
			int num = list.Count - value;
			for (int i = 0; i < num; i++)
			{
				try
				{
					File.Delete(list[i]);
				}
				catch
				{
				}
			}
		}

		public void OpenBrowserFromMenu()
		{
			_hud.OpenBrowser(ListReplaysNewestFirst());
		}

		public void StartPlayback(string path)
		{
			try
			{
				ReplayData replayData = ReplayFormat.Load(path);
				if (replayData == null)
				{
					_hud.Toast("Invalid replay", 2.5f);
					return;
				}
				Level val = ReplayAccess.FindLevelByName(replayData.LevelResourceName);
				if ((Object)(object)val == (Object)null)
				{
					_hud.Toast("Level not found: " + replayData.LevelName, 3.5f);
					return;
				}
				if (_mode == ReplayMode.Recording)
				{
					_recorder.End();
					_mode = ReplayMode.Idle;
				}
				_pendingReplay = replayData;
				_awaitingPlaybackLevel = true;
				_settling = false;
				_suppressRecording = true;
				IsPlaybackBoot = true;
				ReplaySeed.Activate(replayData.LevelSeed);
				_hud.CloseBrowser();
				_hud.Toast("Loading replay: " + replayData.LevelName, 3f);
				BootPlaybackLevel(val, replayData.LevelsCompleted);
			}
			catch (Exception ex)
			{
				_hud.Toast("Load failed", 2.5f);
				EmpressReplaysPlugin.Log.LogError((object)("Replay load failed: " + ex));
				IsPlaybackBoot = false;
				_awaitingPlaybackLevel = false;
				_suppressRecording = false;
			}
		}

		private void BootPlaybackLevel(Level level, int levelsCompleted)
		{
			GameManager instance = GameManager.instance;
			if (instance != null)
			{
				instance.SetConnectRandom(false);
			}
			GameManager instance2 = GameManager.instance;
			if (instance2 != null)
			{
				instance2.SetLobbyType((LobbyTypes)0);
			}
			RunManager.instance.ResetProgress();
			ReplayAccess.SetLevelsCompleted(levelsCompleted);
			ReplayAccess.SetDebugLevel(level);
			ReplayAccess.SetLevelCurrent(level);
			RunManager.instance.ChangeLevel(true, false, (ChangeLevelType)1);
		}

		public void OnLevelGenerateDone()
		{
			if (!IsPlaybackBoot)
			{
				ReplaySeed.Deactivate();
			}
		}

		private bool LevelFullyLoaded()
		{
			if (!ReplayAccess.IsGameStateMain())
			{
				return false;
			}
			if (!ReplayAccess.IsLevelGenerated())
			{
				return false;
			}
			if ((Object)(object)ReplayAccess.GetLocalAvatar() == (Object)null)
			{
				return false;
			}
			if (!ReplayAccess.IsLoadingComplete())
			{
				return false;
			}
			return true;
		}

		private void BeginPlaybackInLevel()
		{
			//IL_0093: 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_00b8: 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)
			_awaitingPlaybackLevel = false;
			_settling = false;
			IsPlaybackBoot = false;
			ReplaySeed.Deactivate();
			ReplayEnvironment.Capture();
			HashSet<string> movedPropNames = CollectMovedPropNames(_pendingReplay);
			_levelOverlay.Build(_pendingReplay, movedPropNames);
			_player.Load(_pendingReplay);
			ReplayLiveSuppressor.SetMovedPropNames(movedPropNames);
			ReplayLiveSuppressor.Suppress(suppress: true);
			_mode = ReplayMode.Playback;
			_playerTargets = _player.PlayerGhosts;
			_targetIndex = LocalPlayerIndex(_playerTargets);
			_rehideTimer = 1f;
			Vector3 startPosition = FirstPlayerPosition(_pendingReplay) + new Vector3(0f, 4f, -6f);
			_camera.Begin(startPosition, Quaternion.Euler(20f, 0f, 0f));
			_camera.SetMode(ReplayViewMode.FirstPerson);
			UpdateCameraTarget();
			_player.Play();
			Time.timeScale = 0f;
			_hud.Toast("Playing " + _pendingReplay.LevelName, 3f);
		}

		private void UpdateDeathFollow()
		{
			List<ReplayGhost> playerGhosts = _player.PlayerGhosts;
			if (playerGhosts.Count == 0)
			{
				return;
			}
			int index = Mathf.Clamp(_targetIndex, 0, playerGhosts.Count - 1);
			ReplayGhost replayGhost = playerGhosts[index];
			if (!((Object)(object)replayGhost.Root == (Object)null) && ((Component)replayGhost.Root).gameObject.activeSelf)
			{
				if ((Object)(object)replayGhost.Root != (Object)null)
				{
					_camera.FollowTarget = replayGhost.Root;
				}
				return;
			}
			ReplayGhost deathHeadGhost = _player.GetDeathHeadGhost();
			if (deathHeadGhost != null && !((Object)(object)deathHeadGhost.Root == (Object)null))
			{
				_camera.FollowTarget = deathHeadGhost.Root;
				if (_camera.Mode == ReplayViewMode.FirstPerson)
				{
					_camera.SetMode(ReplayViewMode.ThirdPerson);
				}
			}
		}

		private void PushFollowAim()
		{
			//IL_0050: 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)
			List<ReplayGhost> playerGhosts = _player.PlayerGhosts;
			if (playerGhosts.Count == 0)
			{
				_camera.SetFollowAim(valid: false, Quaternion.identity);
				return;
			}
			int index = Mathf.Clamp(_targetIndex, 0, playerGhosts.Count - 1);
			ReplayGhost replayGhost = playerGhosts[index];
			_camera.SetFollowAim(replayGhost.HasAim, replayGhost.CurrentAim);
		}

		private static HashSet<string> CollectMovedPropNames(ReplayData data)
		{
			HashSet<string> hashSet = new HashSet<string>();
			if (data == null)
			{
				return hashSet;
			}
			for (int i = 0; i < data.Actors.Count; i++)
			{
				ReplayActor replayActor = data.Actors[i];
				if (replayActor.Kind == ReplayActorKind.Prop && ReplayPlayer.ActorMoved(replayActor))
				{
					hashSet.Add(replayActor.DisplayName);
				}
			}
			return hashSet;
		}

		private static int LocalPlayerIndex(List<ReplayGhost> players)
		{
			for (int i = 0; i < players.Count; i++)
			{
				if (players[i].Actor != null && players[i].Actor.IsLocalPlayer)
				{
					return i;
				}
			}
			return 0;
		}

		private void ApplyFirstPersonHiding()
		{
			List<ReplayGhost> playerGhosts = _player.PlayerGhosts;
			if (playerGhosts.Count != 0)
			{
				bool flag = _camera.Mode == ReplayViewMode.FirstPerson;
				int num = Mathf.Clamp(_targetIndex, 0, playerGhosts.Count - 1);
				for (int i = 0; i < playerGhosts.Count; i++)
				{
					SetGhostRenderers(playerGhosts[i], !flag || i != num);
				}
			}
		}

		private static void SetGhostRenderers(ReplayGhost ghost, bool visible)
		{
			if (ghost == null || ghost.Renderers == null)
			{
				return;
			}
			for (int i = 0; i < ghost.Renderers.Length; i++)
			{
				Renderer val = ghost.Renderers[i];
				if ((Object)(object)val != (Object)null && val.enabled != visible)
				{
					val.enabled = visible;
				}
			}
		}

		public void ApplyCameraPosition(CameraPosition cameraPosition)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (_mode == ReplayMode.Playback && _camera.Active && !((Object)(object)cameraPosition == (Object)null))
			{
				((Component)cameraPosition).transform.position = _camera.Position;
			}
		}

		public void ApplyCameraAim(CameraAim cameraAim)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (_mode == ReplayMode.Playback && _camera.Active && !((Object)(object)cameraAim == (Object)null))
			{
				((Component)cameraAim).transform.rotation = _camera.Rotation;
			}
		}

		public void StopPlayback()
		{
			if (_mode == ReplayMode.Playback)
			{
				Time.timeScale = 1f;
				ReplayEnvironment.Clear();
				_player.Unload();
				_levelOverlay.Clear();
				_camera.End();
				ReplayLiveSuppressor.Suppress(suppress: false);
				_mode = ReplayMode.Idle;
				_pendingReplay = null;
				_hud.Toast("Playback ended, leaving", 2f);
				if ((Object)(object)RunManager.instance != (Object)null)
				{
					ReplayAccess.SetDebugLevel(null);
					((MonoBehaviour)this).StartCoroutine(LeaveAfterDelay());
				}
			}
		}

		private IEnumerator LeaveAfterDelay()
		{
			yield return (object)new WaitForSecondsRealtime(0.5f);
			if ((Object)(object)RunManager.instance != (Object)null)
			{
				((MonoBehaviour)this).StartCoroutine(RunManager.instance.LeaveToMainMenu());
			}
		}

		public void DeleteReplay(string path)
		{
			try
			{
				File.Delete(path);
			}
			catch
			{
			}
		}

		public List<string> ListReplaysNewestFirst()
		{
			List<string> list = ListReplays();
			list.Sort(CompareByWriteTimeDesc);
			return list;
		}

		private void HandlePlaybackInput()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(EmpressReplaysPlugin.Settings.ViewModeKey.Value))
			{
				_camera.CycleMode();
				UpdateCameraTarget();
				_hud.Toast("View: " + _camera.Mode, 1.5f);
			}
			if (Input.GetKeyDown(EmpressReplaysPlugin.Settings.NextTargetKey.Value))
			{
				CycleTarget();
			}
			if (Input.GetKeyDown(EmpressReplaysPlugin.Settings.ExitKey.Value))
			{
				StopPlayback();
			}
		}

		private void CycleTarget()
		{
			_playerTargets = _player.PlayerGhosts;
			if (_playerTargets.Count != 0)
			{
				_targetIndex = (_targetIndex + 1) % _playerTargets.Count;
				UpdateCameraTarget();
				_hud.Toast("Spectating " + _playerTargets[_targetIndex].Actor.DisplayName, 2f);
			}
		}

		private void UpdateCameraTarget()
		{
			_playerTargets = _player.PlayerGhosts;
			if (_playerTargets.Count == 0)
			{
				_camera.FollowTarget = null;
				if (_camera.Mode != ReplayViewMode.Free)
				{
					_camera.SetMode(ReplayViewMode.Free);
				}
			}
			else
			{
				_targetIndex = Mathf.Clamp(_targetIndex, 0, _playerTargets.Count - 1);
				_camera.FollowTarget = _playerTargets[_targetIndex].Root;
			}
		}

		private List<string> ListReplays()
		{
			List<string> list = new List<string>();
			try
			{
				if (Directory.Exists(EmpressReplaysPlugin.ReplayFolder))
				{
					list.AddRange(Directory.GetFiles(EmpressReplaysPlugin.ReplayFolder, "*.emrly"));
				}
			}
			catch
			{
			}
			return list;
		}

		private static int CompareByWriteTimeDesc(string a, string b)
		{
			return File.GetLastWriteTimeUtc(b).CompareTo(File.GetLastWriteTimeUtc(a));
		}

		private static int CompareByWriteTimeAsc(string a, string b)
		{
			return File.GetLastWriteTimeUtc(a).CompareTo(File.GetLastWriteTimeUtc(b));
		}

		private void HandleSceneChange()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			int handle = ((Scene)(ref activeScene)).handle;
			if (handle != _sceneHandle)
			{
				_sceneHandle = handle;
				_levelOverlay.Clear();
				if (_mode == ReplayMode.Playback)
				{
					StopPlayback();
				}
				else if (_mode == ReplayMode.Recording)
				{
					ReplayData data = _recorder.End();
					SaveReplay(data);
				}
				_mode = ReplayMode.Idle;
				_levelRecorded = false;
			}
		}

		private static bool InLevel()
		{
			if (ReplayAccess.IsGameStateMain() && (Object)(object)LevelGenerator.Instance != (Object)null)
			{
				return !SemiFunc.MenuLevel();
			}
			return false;
		}

		private static Vector3 FirstPlayerPosition(ReplayData data)
		{
			//IL_0046: 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)
			for (int i = 0; i < data.Actors.Count; i++)
			{
				ReplayActor replayActor = data.Actors[i];
				if (replayActor.Kind == ReplayActorKind.Player && replayActor.Positions.Count > 0)
				{
					return replayActor.Positions[0];
				}
			}
			return Vector3.zero;
		}

		private static string SafeName(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return "Level";
			}
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			string text = raw;
			for (int i = 0; i < invalidFileNameChars.Length; i++)
			{
				text = text.Replace(invalidFileNameChars[i], '_');
			}
			return text.Replace(' ', '_');
		}
	}
	internal static class ReplayEnvironment
	{
		private static bool _captured;

		private static bool _fog;

		private static Color _fogColor;

		private static FogMode _fogMode;

		private static float _fogStart;

		private static float _fogEnd;

		private static float _fogDensity;

		private static AmbientMode _ambientMode;

		private static Color _ambientLight;

		private static Color _ambientSky;

		private static Color _ambientEquator;

		private static Color _ambientGround;

		private static float _ambientIntensity;

		public static void Capture()
		{
			//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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0064: 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)
			_fog = RenderSettings.fog;
			_fogColor = RenderSettings.fogColor;
			_fogMode = RenderSettings.fogMode;
			_fogStart = RenderSettings.fogStartDistance;
			_fogEnd = RenderSettings.fogEndDistance;
			_fogDensity = RenderSettings.fogDensity;
			_ambientMode = RenderSettings.ambientMode;
			_ambientLight = RenderSettings.ambientLight;
			_ambientSky = RenderSettings.ambientSkyColor;
			_ambientEquator = RenderSettings.ambientEquatorColor;
			_ambientGround = RenderSettings.ambientGroundColor;
			_ambientIntensity = RenderSettings.ambientIntensity;
			_captured = true;
		}

		public static void Apply()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (_captured)
			{
				RenderSettings.fog = _fog;
				RenderSettings.fogColor = _fogColor;
				RenderSettings.fogMode = _fogMode;
				RenderSettings.fogStartDistance = _fogStart;
				RenderSettings.fogEndDistance = _fogEnd;
				RenderSettings.fogDensity = _fogDensity;
				RenderSettings.ambientMode = _ambientMode;
				RenderSettings.ambientLight = _ambientLight;
				RenderSettings.ambientSkyColor = _ambientSky;
				RenderSettings.ambientEquatorColor = _ambientEquator;
				RenderSettings.ambientGroundColor = _ambientGround;
				RenderSettings.ambientIntensity = _ambientIntensity;
			}
		}

		public static void Clear()
		{
			_captured = false;
		}
	}
	internal enum ReplayActorKind : byte
	{
		Player,
		Enemy,
		Valuable,
		Prop
	}
	internal sealed class ReplayModule
	{
		public string ResourcePath;

		public string PrefabName = string.Empty;

		public Vector3 Position;

		public Quaternion Rotation;

		public bool[] RendererStates;

		public int[] RendererPathHashes;
	}
	internal sealed class ReplayActor
	{
		public int ActorId;

		public ReplayActorKind Kind;

		public string DisplayName;

		public string PrefabPath = string.Empty;

		public Vector3 BaseScale = Vector3.one;

		public bool IsLocalPlayer;

		public readonly List<int> FrameIndices = new List<int>();

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

		public readonly List<Quaternion> Rotations = new List<Quaternion>();

		public readonly List<bool> Active = new List<bool>();

		public readonly List<Quaternion> AimRotations = new List<Quaternion>();

		public bool HasAnim;

		public readonly List<ReplayAnimParam> AnimParams = new List<ReplayAnimParam>();

		public readonly List<float[]> AnimSamples = new List<float[]>();

		public readonly List<float> AnimSpeeds = new List<float>();
	}
	internal sealed class ReplayData
	{
		public string LevelName = string.Empty;

		public string LevelResourceName = string.Empty;

		public int LevelSeed;

		public int LevelsCompleted;

		public float TickInterval = 0.05f;

		public int FrameCount;

		public float Duration;

		public DateTime RecordedAt = DateTime.Now;

		public readonly List<ReplayModule> Modules = new List<ReplayModule>();

		public readonly List<ReplayActor> Actors = new List<ReplayActor>();
	}
	internal static class ReplayFormat
	{
		private static readonly char[] Magic = new char[8] { 'E', 'M', 'P', 'R', 'P', 'L', 'Y', '3' };

		public const string Extension = ".emrly";

		public static void Save(string path, ReplayData data)
		{
			//IL_00e8: 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_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			using FileStream output = File.Create(path);
			using BinaryWriter binaryWriter = new BinaryWriter(output);
			binaryWriter.Write(Magic);
			binaryWriter.Write((byte)8);
			binaryWriter.Write(data.LevelName ?? string.Empty);
			binaryWriter.Write(data.LevelResourceName ?? string.Empty);
			binaryWriter.Write(data.LevelSeed);
			binaryWriter.Write(data.LevelsCompleted);
			binaryWriter.Write(data.TickInterval);
			binaryWriter.Write(data.FrameCount);
			binaryWriter.Write(data.Duration);
			binaryWriter.Write(data.RecordedAt.ToBinary());
			binaryWriter.Write(data.Modules.Count);
			for (int i = 0; i < data.Modules.Count; i++)
			{
				ReplayModule replayModule = data.Modules[i];
				binaryWriter.Write(replayModule.ResourcePath ?? string.Empty);
				binaryWriter.Write(replayModule.PrefabName ?? string.Empty);
				WriteVector(binaryWriter, replayModule.Position);
				WriteQuaternion(binaryWriter, replayModule.Rotation);
				int num = ((replayModule.RendererStates != null) ? replayModule.RendererStates.Length : 0);
				binaryWriter.Write(num);
				for (int j = 0; j < num; j++)
				{
					binaryWriter.Write(replayModule.RendererStates[j]);
				}
				for (int k = 0; k < num; k++)
				{
					binaryWriter.Write((replayModule.RendererPathHashes != null && k < replayModule.RendererPathHashes.Length) ? replayModule.RendererPathHashes[k] : 0);
				}
			}
			binaryWriter.Write(data.Actors.Count);
			for (int l = 0; l < data.Actors.Count; l++)
			{
				ReplayActor replayActor = data.Actors[l];
				binaryWriter.Write(replayActor.ActorId);
				binaryWriter.Write((byte)replayActor.Kind);
				binaryWriter.Write(replayActor.DisplayName ?? string.Empty);
				binaryWriter.Write(replayActor.PrefabPath ?? string.Empty);
				WriteVector(binaryWriter, replayActor.BaseScale);
				binaryWriter.Write(replayActor.IsLocalPlayer);
				int count = replayActor.FrameIndices.Count;
				binaryWriter.Write(count);
				for (int m = 0; m < count; m++)
				{
					binaryWriter.Write(replayActor.FrameIndices[m]);
					WriteVector(binaryWriter, replayActor.Positions[m]);
					WriteQuaternion(binaryWriter, replayActor.Rotations[m]);
					binaryWriter.Write(replayActor.Active[m]);
				}
				int count2 = replayActor.AimRotations.Count;
				binaryWriter.Write(count2);
				for (int n = 0; n < count2; n++)
				{
					WriteQuaternion(binaryWriter, replayActor.AimRotations[n]);
				}
				bool flag = replayActor.HasAnim && replayActor.AnimParams.Count > 0 && replayActor.AnimSamples.Count == count;
				binaryWriter.Write(flag);
				if (!flag)
				{
					continue;
				}
				binaryWriter.Write(replayActor.AnimParams.Count);
				for (int num2 = 0; num2 < replayActor.AnimParams.Count; num2++)
				{
					ReplayAnimParam replayAnimParam = replayActor.AnimParams[num2];
					binaryWriter.Write(replayAnimParam.Name ?? string.Empty);
					binaryWriter.Write((byte)replayAnimParam.Type);
				}
				binaryWriter.Write(replayActor.AnimSamples.Count);
				for (int num3 = 0; num3 < replayActor.AnimSamples.Count; num3++)
				{
					float[] array = replayActor.AnimSamples[num3];
					for (int num4 = 0; num4 < replayActor.AnimParams.Count; num4++)
					{
						binaryWriter.Write((array != null && num4 < array.Length) ? array[num4] : 0f);
					}
					binaryWriter.Write((num3 < replayActor.AnimSpeeds.Count) ? replayActor.AnimSpeeds[num3] : 1f);
				}
			}
		}

		public static ReplayData Load(string path)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			using FileStream input = File.OpenRead(path);
			using BinaryReader binaryReader = new BinaryReader(input);
			char[] array = binaryReader.ReadChars(Magic.Length);
			for (int i = 0; i < Magic.Length; i++)
			{
				if (array[i] != Magic[i])
				{
					return null;
				}
			}
			byte b = binaryReader.ReadByte();
			ReplayData replayData = new ReplayData
			{
				LevelName = binaryReader.ReadString(),
				LevelResourceName = binaryReader.ReadString(),
				LevelSeed = binaryReader.ReadInt32(),
				LevelsCompleted = binaryReader.ReadInt32(),
				TickInterval = binaryReader.ReadSingle(),
				FrameCount = binaryReader.ReadInt32(),
				Duration = binaryReader.ReadSingle(),
				RecordedAt = DateTime.FromBinary(binaryReader.ReadInt64())
			};
			int num = binaryReader.ReadInt32();
			for (int j = 0; j < num; j++)
			{
				ReplayModule replayModule = new ReplayModule
				{
					ResourcePath = binaryReader.ReadString()
				};
				if (b >= 6)
				{
					replayModule.PrefabName = binaryReader.ReadString();
				}
				replayModule.Position = ReadVector(binaryReader);
				replayModule.Rotation = ReadQuaternion(binaryReader);
				if (b >= 7)
				{
					int num2 = binaryReader.ReadInt32();
					if (num2 > 0)
					{
						replayModule.RendererStates = new bool[num2];
						for (int k = 0; k < num2; k++)
						{
							replayModule.RendererStates[k] = binaryReader.ReadBoolean();
						}
						if (b >= 8)
						{
							replayModule.RendererPathHashes = new int[num2];
							for (int l = 0; l < num2; l++)
							{
								replayModule.RendererPathHashes[l] = binaryReader.ReadInt32();
							}
						}
					}
				}
				replayData.Modules.Add(replayModule);
			}
			int num3 = binaryReader.ReadInt32();
			for (int m = 0; m < num3; m++)
			{
				ReplayActor replayActor = new ReplayActor
				{
					ActorId = binaryReader.ReadInt32(),
					Kind = (ReplayActorKind)binaryReader.ReadByte(),
					DisplayName = binaryReader.ReadString(),
					PrefabPath = binaryReader.ReadString(),
					BaseScale = ReadVector(binaryReader)
				};
				if (b >= 4)
				{
					replayActor.IsLocalPlayer = binaryReader.ReadBoolean();
				}
				int num4 = binaryReader.ReadInt32();
				for (int n = 0; n < num4; n++)
				{
					replayActor.FrameIndices.Add(binaryReader.ReadInt32());
					replayActor.Positions.Add(ReadVector(binaryReader));
					replayActor.Rotations.Add(ReadQuaternion(binaryReader));
					replayActor.Active.Add(binaryReader.ReadBoolean());
				}
				if (b >= 4)
				{
					int num5 = binaryReader.ReadInt32();
					for (int num6 = 0; num6 < num5; num6++)
					{
						replayActor.AimRotations.Add(ReadQuaternion(binaryReader));
					}
				}
				if (b >= 5)
				{
					replayActor.HasAnim = binaryReader.ReadBoolean();
					if (replayActor.HasAnim)
					{
						int num7 = binaryReader.ReadInt32();
						for (int num8 = 0; num8 < num7; num8++)
						{
							string text = binaryReader.ReadString();
							replayActor.AnimParams.Add(new ReplayAnimParam
							{
								Name = text,
								Type = (ReplayAnimParamType)binaryReader.ReadByte(),
								Hash = Animator.StringToHash(text)
							});
						}
						int num9 = binaryReader.ReadInt32();
						for (int num10 = 0; num10 < num9; num10++)
						{
							float[] array2 = new float[num7];
							for (int num11 = 0; num11 < num7; num11++)
							{
								array2[num11] = binaryReader.ReadSingle();
							}
							replayActor.AnimSamples.Add(array2);
							replayActor.AnimSpeeds.Add(binaryReader.ReadSingle());
						}
					}
				}
				replayData.Actors.Add(replayActor);
			}
			return replayData;
		}

		public static string PeekLevelName(string path)
		{
			try
			{
				using FileStream input = File.OpenRead(path);
				using BinaryReader binaryReader = new BinaryReader(input);
				char[] array = binaryReader.ReadChars(Magic.Length);
				for (int i = 0; i < Magic.Length; i++)
				{
					if (array[i] != Magic[i])
					{
						return null;
					}
				}
				binaryReader.ReadByte();
				return binaryReader.ReadString();
			}
			catch
			{
				return null;
			}
		}

		private static void WriteVector(BinaryWriter writer, Vector3 value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(value.x);
			writer.Write(value.y);
			writer.Write(value.z);
		}

		private static Vector3 ReadVector(BinaryReader reader)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
		}

		private static void WriteQuaternion(BinaryWriter writer, Quaternion value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(value.x);
			writer.Write(value.y);
			writer.Write(value.z);
			writer.Write(value.w);
		}

		private static Quaternion ReadQuaternion(BinaryReader reader)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return new Quaternion(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
		}
	}
	internal sealed class ReplayHud : MonoBehaviour
	{
		private ReplayController _controller;

		private ReplayMode _mode;

		private int _recordFrames;

		private ReplayPlayer _player;

		private ReplayCamera _camera;

		private bool _browserVisible;

		private readonly List<string> _files = new List<string>();

		private Vector2 _scroll;

		private string _toast = string.Empty;

		private float _toastUntil;

		private Texture2D _panel;

		private GUIStyle _title;

		private GUIStyle _item;

		private GUIStyle _small;

		private GUIStyle _badge;

		private bool _stylesReady;

		public static ReplayHud Create(ReplayController controller)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: