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 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 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 AutoRecord; public readonly ConfigEntry ShowRecordingIndicator; public readonly ConfigEntry DebugLogs; public readonly ConfigEntry MaxReplays; public readonly ConfigEntry TickInterval; public readonly ConfigEntry CameraSpeed; public readonly ConfigEntry LookSensitivity; public readonly ConfigEntry ViewModeKey; public readonly ConfigEntry NextTargetKey; public readonly ConfigEntry 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("Recording", "AutoRecord", true, "Automatically record every match and save it on level completion."); ShowRecordingIndicator = config.Bind("Recording", "ShowRecordingIndicator", false, "Show the blinking REC indicator in-game while a match is being recorded."); DebugLogs = config.Bind("Debug", "DebugLogs", false, "Write verbose diagnostic logs to the console (for troubleshooting only)."); MaxReplays = config.Bind("Recording", "MaxReplays", 100, new ConfigDescription("Maximum saved replays before the oldest is overwritten.", (AcceptableValueBase)(object)new AcceptableValueRange(5, 500), Array.Empty())); TickInterval = config.Bind("Recording", "TickInterval", 0.05f, new ConfigDescription("Seconds between recorded snapshots (lower = smoother, bigger files).", (AcceptableValueBase)(object)new AcceptableValueRange(0.02f, 0.25f), Array.Empty())); CameraSpeed = config.Bind("Playback", "CameraSpeed", 8f, new ConfigDescription("Free-camera move speed.", (AcceptableValueBase)(object)new AcceptableValueRange(2f, 30f), Array.Empty())); LookSensitivity = config.Bind("Playback", "LookSensitivity", 2.2f, new ConfigDescription("Camera look sensitivity.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 6f), Array.Empty())); ViewModeKey = config.Bind("Playback", "ViewModeKey", (KeyCode)118, "Cycles first-person / third-person orbit / free camera."); NextTargetKey = config.Bind("Playback", "NextTargetKey", (KeyCode)9, "Switches which player you are spectating."); ExitKey = config.Bind("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 GetPlayerList() { if (GameDirectorPlayerListField != null && (Object)(object)GameDirector.instance != (Object)null) { return GameDirectorPlayerListField.GetValue(GameDirector.instance) as List; } 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(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(); } public static Animator GetEnemyAnimator(Transform enemyTransform) { if ((Object)(object)enemyTransform == (Object)null) { return null; } Animator[] componentsInChildren = ((Component)enemyTransform).GetComponentsInChildren(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 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 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 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 dictionary) { foreach (KeyValuePair 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 dictionary2) { foreach (KeyValuePair 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(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 GetSpawnedEnemies() { EnemyDirector enemyDirector = GetEnemyDirector(); if ((Object)(object)enemyDirector == (Object)null || EnemyDirectorSpawnedField == null) { return null; } return EnemyDirectorSpawnedField.GetValue(enemyDirector) as List; } 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("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("Enemies/" + text2); if ((Object)(object)val != (Object)null) { return val; } val = Resources.Load("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) : 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 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) : 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 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 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 dictionary = (((Object)(object)levelCurrent != (Object)null) ? BuildLevelPrefabPathMap(levelCurrent) : new Dictionary()); 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(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() != (Object)null) && !((Object)(object)((Component)child).GetComponent() != (Object)null) && !((Object)(object)((Component)child).GetComponent() != (Object)null) && !((Object)(object)((Component)child).GetComponent() != (Object)null)) { return (Object)(object)((Component)child).GetComponentInChildren(true) != (Object)null; } return true; } public static GameObject ResolveModulePrefab(string resourcePath, string prefabName, Dictionary 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 BuildLevelPrefabObjectMap(Level level) { Dictionary dictionary = new Dictionary(); 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 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 map, object owner, FieldInfo field) { if (map != null && owner != null && !(field == null) && field.GetValue(owner) is List list) { for (int i = 0; i < list.Count; i++) { AddPrefabObject(map, list[i]); } } } private static void AddPrefabObject(Dictionary 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 BuildLevelPrefabPathMap(Level level) { Dictionary dictionary = new Dictionary(); 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 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 map, object owner, FieldInfo field) { if (map != null && owner != null && !(field == null) && field.GetValue(owner) is List list) { for (int i = 0; i < list.Count; i++) { AddPrefabRef(map, list[i]); } } } private static void AddPrefabRef(Dictionary 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 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 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) : 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) : null, cleanedName); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static GameObject FindValuablePrefabInList(List 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 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 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 list = new List(); 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 hashSet = new HashSet(); 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() == (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 _playerTargets = new List(); 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(); 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 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 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 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 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 CollectMovedPropNames(ReplayData data) { HashSet hashSet = new HashSet(); 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 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 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 ListReplaysNewestFirst() { List 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 ListReplays() { List list = new List(); 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 FrameIndices = new List(); public readonly List Positions = new List(); public readonly List Rotations = new List(); public readonly List Active = new List(); public readonly List AimRotations = new List(); public bool HasAnim; public readonly List AnimParams = new List(); public readonly List AnimSamples = new List(); public readonly List AnimSpeeds = new List(); } 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 Modules = new List(); public readonly List Actors = new List(); } 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 _files = new List(); 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: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown GameObject val = new GameObject("Empress Replay HUD"); val.transform.parent = null; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)val); ReplayHud replayHud = val.AddComponent(); replayHud._controller = controller; return replayHud; } public void UpdateState(ReplayMode mode, int recordFrames, ReplayPlayer player, ReplayCamera camera) { _mode = mode; _recordFrames = recordFrames; _player = player; _camera = camera; } public void OpenBrowser(List files) { _files.Clear(); _files.AddRange(files); _browserVisible = true; } public void CloseBrowser() { _browserVisible = false; } public bool WantsCursor() { if (!_browserVisible) { return _mode == ReplayMode.Playback; } return true; } public void Toast(string text, float duration) { _toast = text ?? string.Empty; _toastUntil = Time.unscaledTime + duration; } private void OnGUI() { EnsureStyles(); if (_mode == ReplayMode.Recording && EmpressReplaysPlugin.Settings.ShowRecordingIndicator.Value) { DrawRecordBadge(); } if (_mode == ReplayMode.Playback && _player != null) { DrawPlaybackBar(); } if (_browserVisible) { DrawBrowser(); } if (Time.unscaledTime < _toastUntil) { DrawToast(); } } private void DrawRecordBadge() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width - 240f, 20f, 220f, 40f); GUI.color = new Color(0f, 0f, 0f, 0.55f); GUI.DrawTexture(val, (Texture)(object)PanelTexture()); GUI.color = ((Mathf.FloorToInt(Time.unscaledTime * 2f) % 2 == 0) ? new Color(1f, 0.2f, 0.2f) : new Color(0.6f, 0.1f, 0.1f)); float seconds = (float)_recordFrames * EmpressReplaysPlugin.Settings.TickInterval.Value; GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 6f, ((Rect)(ref val)).width, 28f), "● REC " + FormatTime(seconds), _badge); GUI.color = Color.white; } private void DrawPlaybackBar() { //IL_005e: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) float num = (float)Screen.width * 0.72f; float num2 = ((float)Screen.width - num) * 0.5f; float num3 = (float)Screen.height - 96f; Rect val = default(Rect); ((Rect)(ref val))..ctor(num2 - 16f, num3 - 48f, num + 32f, 132f); GUI.color = new Color(0f, 0f, 0f, 0.72f); GUI.DrawTexture(val, (Texture)(object)PanelTexture()); GUI.color = Color.white; string text = ((_camera != null) ? _camera.Mode.ToString() : "View"); GUI.Label(new Rect(((Rect)(ref val)).x + 16f, ((Rect)(ref val)).y + 6f, num, 24f), "EMPRESS THEATER - " + _player.LevelName + " [" + text + "]", _title); string text2 = (_player.Playing ? "❚❚" : "▶"); if (GUI.Button(new Rect(num2, num3, 50f, 30f), text2)) { _player.TogglePlay(); } if (GUI.Button(new Rect(num2 + 56f, num3, 54f, 30f), "« 5s")) { _player.Step(-5f); } if (GUI.Button(new Rect(num2 + 114f, num3, 54f, 30f), "5s »")) { _player.Step(5f); } if (GUI.Button(new Rect(num2 + 172f, num3, 70f, 30f), _player.Speed.ToString("0.0") + "x")) { _player.Speed = ((_player.Speed >= 4f) ? 0.5f : (_player.Speed + 0.5f)); } if (GUI.Button(new Rect(num2 + 246f, num3, 90f, 30f), "View (V)")) { _camera?.CycleMode(); } if (GUI.Button(new Rect(num2 + num - 80f, num3, 80f, 30f), "✖ Exit")) { _controller.StopPlayback(); } Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num2, num3 + 40f, num, 18f); GUI.color = new Color(0.15f, 0.15f, 0.18f, 0.95f); GUI.DrawTexture(val2, (Texture)(object)PanelTexture()); float num4 = ((_player.Duration > 0f) ? (_player.Time / _player.Duration) : 0f); GUI.color = new Color(0.9f, 0.4f, 0.85f); GUI.DrawTexture(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width * num4, ((Rect)(ref val2)).height), (Texture)(object)PanelTexture()); GUI.color = Color.white; float num5 = GUI.HorizontalSlider(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, 14f), num4, 0f, 1f); if (Mathf.Abs(num5 - num4) > 0.0005f) { _player.Scrub(num5); } GUI.Label(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + 20f, num, 20f), FormatTime(_player.Time) + " / " + FormatTime(_player.Duration) + " [Tab] switch player [RMB] look", _small); } private void DrawBrowser() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) float num = 560f; float num2 = 440f; Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2); GUI.color = new Color(0f, 0f, 0f, 0.92f); GUI.DrawTexture(val, (Texture)(object)PanelTexture()); GUI.color = new Color(0.9f, 0.5f, 0.9f); GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 10f, num, 30f), "EMPRESS REPLAYS", _title); GUI.color = Color.white; if (_files.Count == 0) { GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 50f, num - 40f, 30f), "No replays yet. Finish a match to save one.", _small); } Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 16f, ((Rect)(ref val)).y + 50f, num - 32f, num2 - 110f); float num3 = 50f; _scroll = GUI.BeginScrollView(val2, _scroll, new Rect(0f, 0f, ((Rect)(ref val2)).width - 20f, (float)_files.Count * num3)); Rect val3 = default(Rect); for (int i = 0; i < _files.Count; i++) { ((Rect)(ref val3))..ctor(0f, (float)i * num3, ((Rect)(ref val2)).width - 20f, num3 - 6f); GUI.color = new Color(0.12f, 0.12f, 0.16f, 0.85f); GUI.DrawTexture(val3, (Texture)(object)PanelTexture()); GUI.color = Color.white; string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(_files[i]); GUI.Label(new Rect(((Rect)(ref val3)).x + 10f, ((Rect)(ref val3)).y + 4f, ((Rect)(ref val3)).width - 150f, 24f), fileNameWithoutExtension, _item); if (GUI.Button(new Rect(((Rect)(ref val3)).xMax - 150f, ((Rect)(ref val3)).y + 10f, 68f, 30f), "▶ Play")) { _controller.StartPlayback(_files[i]); } if (GUI.Button(new Rect(((Rect)(ref val3)).xMax - 78f, ((Rect)(ref val3)).y + 10f, 70f, 30f), "Delete")) { _controller.DeleteReplay(_files[i]); _files.RemoveAt(i); break; } } GUI.EndScrollView(); if (GUI.Button(new Rect(((Rect)(ref val)).x + num - 110f, ((Rect)(ref val)).yMax - 44f, 96f, 32f), "Close")) { _browserVisible = false; } } private void DrawToast() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Rect val = new Rect(0f, (float)Screen.height * 0.72f, (float)Screen.width, 40f); GUI.color = new Color(1f, 0.6f, 0.9f); GUI.Label(val, _toast, _title); GUI.color = Color.white; } private static string FormatTime(float seconds) { if (seconds < 0f) { seconds = 0f; } int num = Mathf.FloorToInt(seconds / 60f); int num2 = Mathf.FloorToInt(seconds % 60f); return num.ToString("00") + ":" + num2.ToString("00"); } private Texture2D PanelTexture() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel == (Object)null) { _panel = new Texture2D(1, 1, (TextureFormat)4, false); _panel.SetPixel(0, 0, Color.white); _panel.Apply(); } return _panel; } private void EnsureStyles() { //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_003f: 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_004c: 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_005f: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //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_009b: 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_00ae: Expected O, but got Unknown if (!_stylesReady) { _title = new GUIStyle(GUI.skin.label) { fontSize = 18, fontStyle = (FontStyle)1, alignment = (TextAnchor)1 }; _item = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; _small = new GUIStyle(GUI.skin.label) { fontSize = 13, alignment = (TextAnchor)3 }; _badge = new GUIStyle(GUI.skin.label) { fontSize = 18, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; _stylesReady = true; } } } internal static class ReplayLayoutCapture { public static string LevelName { get; private set; } = string.Empty; public static string LevelResource { get; private set; } = string.Empty; public static int LevelSeed { get; private set; } public static void BeginLevel(string levelName, string levelResource, int seed) { LevelName = levelName ?? string.Empty; LevelResource = levelResource ?? string.Empty; LevelSeed = seed; } public static void Clear() { LevelName = string.Empty; LevelResource = string.Empty; LevelSeed = 0; } } internal sealed class ReplayLevelOverlay { private GameObject _root; private readonly List _deactivated = new List(); private HashSet _movedPropNames = new HashSet(); public void Build(ReplayData data, HashSet movedPropNames) { //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) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_0084: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) Clear(); _movedPropNames = movedPropNames ?? new HashSet(); if (data == null || data.Modules.Count == 0) { return; } bool flag = ModulesHaveRendererStates(data); if (!flag && LiveLevelMatches(data)) { EmpressReplaysPlugin.DebugLog("Empress Replay: seeded live level matches the recording, using the real level directly."); return; } EmpressReplaysPlugin.DebugLog(flag ? "Empress Replay: rebuilding exact modules from captured renderer states." : "Empress Replay: live level does not match the recording, rebuilding from captured modules."); Dictionary levelPrefabs = ReplayAccess.BuildLevelPrefabObjectMap(ReplayAccess.GetLevelCurrent()); Vector3 liveDoorLocal = Vector3.zero; bool flag2 = false; Transform truckDoorMesh = ReplayAccess.GetTruckDoorMesh(ReplayAccess.FindLiveTruckDoor()); if ((Object)(object)truckDoorMesh != (Object)null) { liveDoorLocal = truckDoorMesh.localPosition; flag2 = true; } HideLiveLevel(); _root = new GameObject("Empress Replay Level"); ((Object)_root).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)_root); int num = 0; int num2 = 0; for (int i = 0; i < data.Modules.Count; i++) { ReplayModule replayModule = data.Modules[i]; GameObject val = ReplayAccess.ResolveModulePrefab(replayModule.ResourcePath, replayModule.PrefabName, levelPrefabs); if ((Object)(object)val == (Object)null) { num2++; EmpressReplaysPlugin.DebugWarn("Replay module unresolved: " + (string.IsNullOrEmpty(replayModule.PrefabName) ? replayModule.ResourcePath : replayModule.PrefabName)); continue; } GameObject val2 = Object.Instantiate(val, replayModule.Position, replayModule.Rotation, _root.transform); ((Object)val2).name = "Replay Level " + ((Object)val).name; if (!val2.activeSelf) { val2.SetActive(true); } ApplyRendererStates(val2, replayModule); if (flag2) { ApplyTruckDoor(val2, liveDoorLocal); } Strip(val2); num++; } EmpressReplaysPlugin.DebugLog("Empress Replay level rebuilt: " + num + " modules (" + num2 + " unresolved)."); } private static bool ModulesHaveRendererStates(ReplayData data) { for (int i = 0; i < data.Modules.Count; i++) { if (data.Modules[i].RendererStates != null && data.Modules[i].RendererStates.Length != 0) { return true; } } return false; } private static void ApplyRendererStates(GameObject clone, ReplayModule module) { bool[] rendererStates = module.RendererStates; if (rendererStates == null || rendererStates.Length == 0) { return; } int[] rendererPathHashes = module.RendererPathHashes; Renderer[] componentsInChildren = clone.GetComponentsInChildren(true); if (rendererPathHashes != null && rendererPathHashes.Length == rendererStates.Length) { Dictionary dictionary = new Dictionary(rendererStates.Length); for (int i = 0; i < rendererPathHashes.Length; i++) { dictionary[rendererPathHashes[i]] = rendererStates[i]; } foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { int key = ReplayAccess.RendererPathHash(clone.transform, ((Component)val).transform); val.enabled = dictionary.TryGetValue(key, out var value) && value; } } } else { if (componentsInChildren.Length != rendererStates.Length) { return; } for (int k = 0; k < componentsInChildren.Length; k++) { if ((Object)(object)componentsInChildren[k] != (Object)null) { componentsInChildren[k].enabled = rendererStates[k]; } } } } private bool LiveLevelMatches(ReplayData data) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) GameObject levelParentObject = ReplayAccess.GetLevelParentObject(); if ((Object)(object)levelParentObject == (Object)null) { return false; } HashSet hashSet = new HashSet(); Transform transform = levelParentObject.transform; for (int i = 0; i < transform.childCount; i++) { Transform child = transform.GetChild(i); if ((Object)(object)child != (Object)null) { hashSet.Add(Cell(child.position)); } } if (hashSet.Count == 0) { return false; } int num = 0; for (int j = 0; j < data.Modules.Count; j++) { if (hashSet.Contains(Cell(data.Modules[j].Position))) { num++; } } int num2 = Mathf.CeilToInt((float)data.Modules.Count * 0.75f); EmpressReplaysPlugin.DebugLog("Empress Replay live-level match: " + num + "/" + data.Modules.Count + " modules align (need " + num2 + ")."); return num >= num2; } private static Vector3Int Cell(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) return new Vector3Int(Mathf.RoundToInt(position.x), Mathf.RoundToInt(position.y), Mathf.RoundToInt(position.z)); } private static void ApplyTruckDoor(GameObject clone, Vector3 liveDoorLocal) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) TruckDoor componentInChildren = clone.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { Transform truckDoorMesh = ReplayAccess.GetTruckDoorMesh(componentInChildren); if ((Object)(object)truckDoorMesh != (Object)null) { truckDoorMesh.localPosition = liveDoorLocal; } } } public void Clear() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; for (int i = 0; i < _deactivated.Count; i++) { if ((Object)(object)_deactivated[i] != (Object)null) { _deactivated[i].SetActive(true); } } _deactivated.Clear(); } private void HideLiveLevel() { GameObject levelParentObject = ReplayAccess.GetLevelParentObject(); if ((Object)(object)levelParentObject == (Object)null) { EmpressReplaysPlugin.DebugWarn("Empress Replay overlay: LevelParent is null, cannot hide the live level."); return; } Transform transform = levelParentObject.transform; int num = 0; for (int i = 0; i < transform.childCount; i++) { GameObject gameObject = ((Component)transform.GetChild(i)).gameObject; if (!((Object)(object)gameObject == (Object)null) && gameObject.activeSelf) { _deactivated.Add(gameObject); gameObject.SetActive(false); num++; } } EmpressReplaysPlugin.DebugLog("Empress Replay overlay hid " + num + " live level objects under '" + ((Object)levelParentObject).name + "'."); } private void Strip(GameObject clone) { HashSet hashSet = CollectHiddenRenderers(clone); Component[] componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); Behaviour[] componentsInChildren2 = (Behaviour[])(object)clone.GetComponentsInChildren(true); DisableAll(componentsInChildren2); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAll(componentsInChildren); Type type = AccessTools.TypeByName("Photon.Pun.PhotonView"); if (type != null) { DestroyAll(clone.GetComponentsInChildren(type, true)); } Renderer[] componentsInChildren3 = clone.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren3) { if (!((Object)(object)val == (Object)null)) { if (hashSet.Contains(val) || !val.enabled) { val.enabled = false; val.forceRenderingOff = true; } else { val.forceRenderingOff = false; val.shadowCastingMode = (ShadowCastingMode)1; ActivateBranch(((Component)val).transform, clone.transform); } } } } private HashSet CollectHiddenRenderers(GameObject clone) { HashSet hashSet = new HashSet(); MonoBehaviour[] componentsInChildren = clone.GetComponentsInChildren(true); foreach (MonoBehaviour val in componentsInChildren) { if ((Object)(object)val == (Object)null || !IsHiddenVolumeType(((object)val).GetType().Name)) { continue; } Renderer[] components = ((Component)val).GetComponents(); for (int j = 0; j < components.Length; j++) { if ((Object)(object)components[j] != (Object)null) { hashSet.Add(components[j]); } } } if (_movedPropNames.Count > 0) { PhysGrabObject[] componentsInChildren2 = clone.GetComponentsInChildren(true); for (int k = 0; k < componentsInChildren2.Length; k++) { if ((Object)(object)componentsInChildren2[k] == (Object)null || !_movedPropNames.Contains(CleanPropName(((Object)componentsInChildren2[k]).name))) { continue; } Renderer[] componentsInChildren3 = ((Component)componentsInChildren2[k]).GetComponentsInChildren(true); for (int l = 0; l < componentsInChildren3.Length; l++) { if ((Object)(object)componentsInChildren3[l] != (Object)null) { hashSet.Add(componentsInChildren3[l]); } } } } return hashSet; } private static string CleanPropName(string raw) { if (string.IsNullOrEmpty(raw)) { return string.Empty; } return raw.Replace("(Clone)", string.Empty).Replace("Valuable ", string.Empty).Trim(); } private static bool IsHiddenVolumeType(string typeName) { if (!typeName.Contains("Volume") && !typeName.Contains("Editor") && !typeName.Contains("SpawnPoint")) { return typeName.Contains("DebugDisplay"); } return true; } private static void DestroyAll(Component[] components) { if (components == null) { return; } for (int i = 0; i < components.Length; i++) { if (!((Object)(object)components[i] == (Object)null)) { try { Object.DestroyImmediate((Object)(object)components[i]); } catch { } } } } private static void DisableAll(Behaviour[] behaviours) { if (behaviours == null) { return; } for (int i = 0; i < behaviours.Length; i++) { if ((Object)(object)behaviours[i] != (Object)null) { behaviours[i].enabled = false; } } } private static void ActivateBranch(Transform leaf, Transform root) { Transform val = leaf; while ((Object)(object)val != (Object)null) { if (!((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } if (!((Object)(object)val == (Object)(object)root)) { val = val.parent; continue; } break; } } } internal static class ReplayLiveSuppressor { private static readonly List _hidden = new List(); private static readonly List _shadowModes = new List(); private static readonly HashSet _managed = new HashSet(); private static readonly List _disabledControllers = new List(); private static HashSet _movedPropNames = new HashSet(); private static bool _active; public static void SetMovedPropNames(HashSet names) { _movedPropNames = names ?? new HashSet(); } public static void Suppress(bool suppress) { if (suppress == _active) { return; } _active = suppress; try { if (suppress) { HideLiveEntities(); } else { RestoreLiveEntities(); } } catch (Exception ex) { EmpressReplaysPlugin.Log.LogError((object)("Empress Replays suppress (" + suppress + ") error: " + ex)); } } public static void RefreshHidden() { if (!_active) { return; } try { HideAvatars(); HideEnemies(); } catch (Exception ex) { EmpressReplaysPlugin.Log.LogError((object)("Empress Replays refresh hide error: " + ex)); } } private static void HideLiveEntities() { HideAvatars(); HideEnemies(); HideValuablesAndProps(); if ((Object)(object)PlayerController.instance != (Object)null) { ((Behaviour)PlayerController.instance).enabled = false; _disabledControllers.Add((Behaviour)(object)PlayerController.instance); } ReplayAccess.SetGameInputDisabled(value: true); } private static void HideAvatars() { List playerList = ReplayAccess.GetPlayerList(); if (playerList == null) { return; } for (int i = 0; i < playerList.Count; i++) { PlayerAvatar val = playerList[i]; if ((Object)(object)val != (Object)null) { HideRenderers(((Component)val).gameObject); } } } private static void HideEnemies() { List spawnedEnemies = ReplayAccess.GetSpawnedEnemies(); if (spawnedEnemies == null) { return; } for (int i = 0; i < spawnedEnemies.Count; i++) { if ((Object)(object)spawnedEnemies[i] != (Object)null) { HideRenderers(((Component)spawnedEnemies[i]).gameObject); } } } private static void HideValuablesAndProps() { ValuableObject[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { HideRenderers(((Component)array[i]).gameObject); } } if (_movedPropNames.Count == 0) { return; } PhysGrabObject[] array2 = Object.FindObjectsOfType(); for (int j = 0; j < array2.Length; j++) { if (!((Object)(object)array2[j] == (Object)null) && !((Object)(object)((Component)array2[j]).GetComponentInParent() != (Object)null)) { string item = ((Object)array2[j]).name.Replace("(Clone)", string.Empty).Replace("Valuable ", string.Empty).Trim(); if (_movedPropNames.Contains(item)) { HideRenderers(((Component)array2[j]).gameObject); } } } } private static void HideRenderers(GameObject root) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } Renderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled) { if (_managed.Add(val)) { _hidden.Add(val); _shadowModes.Add(val.shadowCastingMode); } val.shadowCastingMode = (ShadowCastingMode)0; val.enabled = false; } } } private static void RestoreLiveEntities() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _hidden.Count; i++) { if ((Object)(object)_hidden[i] != (Object)null) { _hidden[i].enabled = true; _hidden[i].shadowCastingMode = _shadowModes[i]; } } for (int j = 0; j < _disabledControllers.Count; j++) { if ((Object)(object)_disabledControllers[j] != (Object)null) { _disabledControllers[j].enabled = true; } } ReplayAccess.SetGameInputDisabled(value: false); _hidden.Clear(); _shadowModes.Clear(); _managed.Clear(); _disabledControllers.Clear(); } } internal static class ReplayMaterials { public static Material Ghost(Color color) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(Shader.Find("Standard")); val.SetFloat("_Mode", 3f); val.SetInt("_SrcBlend", 5); val.SetInt("_DstBlend", 10); val.SetInt("_ZWrite", 0); val.DisableKeyword("_ALPHATEST_ON"); val.EnableKeyword("_ALPHABLEND_ON"); val.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val.renderQueue = 3000; val.color = new Color(color.r, color.g, color.b, 0.55f); if (val.HasProperty("_Glossiness")) { val.SetFloat("_Glossiness", 0.4f); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0.1f); } if (val.HasProperty("_EmissionColor")) { val.EnableKeyword("_EMISSION"); val.SetColor("_EmissionColor", color * 1.4f); val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1; } return val; } } internal static class ReplayModelFactory { public static GameObject CreateActorModel(ReplayActor actor, Transform parent) { GameObject val = TryCloneReal(actor, parent); if ((Object)(object)val != (Object)null) { if ((Object)(object)val.GetComponentInChildren(true) != (Object)null) { return val; } Object.Destroy((Object)(object)val); } return BuildStylized(actor, parent); } private static GameObject TryCloneReal(ReplayActor actor, Transform parent) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) GameObject val = ResolveSource(actor); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = new GameObject("Replay Actor " + actor.DisplayName); val2.transform.SetParent(parent, false); val2.SetActive(false); GameObject val3 = Object.Instantiate(val, val2.transform); ((Object)val3).name = "Replay Model " + actor.DisplayName; val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; StripToVisual(val3, actor.Kind); if (actor.Kind == ReplayActorKind.Player) { SetLayerRecursive(val3.transform, 0); } val2.SetActive(true); return val2; } private static GameObject ResolveSource(ReplayActor actor) { return (GameObject)(actor.Kind switch { ReplayActorKind.Player => LocalAvatarVisual(), ReplayActorKind.Enemy => FindEnemyVisual(actor), ReplayActorKind.Valuable => FindValuableVisual(actor), ReplayActorKind.Prop => FindPropVisual(actor.DisplayName), _ => null, }); } private static GameObject LocalAvatarVisual() { PlayerAvatar localAvatar = ReplayAccess.GetLocalAvatar(); if ((Object)(object)localAvatar == (Object)null) { return null; } return ReplayAccess.GetAvatarVisualRoot(localAvatar); } private static GameObject FindEnemyVisual(ReplayActor actor) { EnemyParent[] array = Object.FindObjectsOfType(true); for (int i = 0; i < array.Length; i++) { if (!(ReplayAccess.GetEnemyName(array[i]) != actor.DisplayName)) { GameObject gameObject = ((Component)array[i]).gameObject; if (HasRenderers(gameObject)) { return gameObject; } } } return FirstWithRenderers(ReplayAccess.FindEnemyPrefab(actor.DisplayName), ReplayAccess.FindEnemyPrefab(actor.PrefabPath), ReplayAccess.FindPrefabByNameInPool(actor.PrefabPath), ReplayAccess.FindPrefabByNameInPool(actor.DisplayName)); } private static bool HasRenderers(GameObject root) { if ((Object)(object)root != (Object)null) { return (Object)(object)root.GetComponentInChildren(true) != (Object)null; } return false; } private static GameObject FirstWithRenderers(params GameObject[] candidates) { for (int i = 0; i < candidates.Length; i++) { if (HasRenderers(candidates[i])) { return candidates[i]; } } return null; } private static GameObject FindValuableVisual(ReplayActor actor) { string displayName = actor.DisplayName; ValuableObject[] array = Object.FindObjectsOfType(true); for (int i = 0; i < array.Length; i++) { if (((Object)array[i]).name.Replace("(Clone)", string.Empty).Replace("Valuable ", string.Empty).Trim() == displayName) { return ((Component)array[i]).gameObject; } } GameObject val = ReplayAccess.FindValuablePrefab(displayName); if ((Object)(object)val != (Object)null) { return val; } val = ReplayAccess.FindValuablePrefab(actor.PrefabPath); if ((Object)(object)val != (Object)null) { return val; } return ReplayAccess.FindPrefabByNameInPool(displayName); } private static GameObject FindPropVisual(string displayName) { PhysGrabObject[] array = Object.FindObjectsOfType(true); for (int i = 0; i < array.Length; i++) { if (!((Object)(object)array[i] == (Object)null) && !((Object)(object)((Component)array[i]).GetComponentInParent() != (Object)null) && ((Object)array[i]).name.Replace("(Clone)", string.Empty).Trim() == displayName) { return ((Component)array[i]).gameObject; } } return ReplayAccess.FindPrefabByNameInPool(displayName); } private static void StripToVisual(GameObject clone, ReplayActorKind kind) { List list = new List(clone.GetComponentsInChildren(true)); int num = 0; while (list.Count > 0 && num++ < 200) { bool flag = false; for (int num2 = list.Count - 1; num2 >= 0; num2--) { MonoBehaviour val = list[num2]; if ((Object)(object)val == (Object)null) { list.RemoveAt(num2); flag = true; } else { try { Object.DestroyImmediate((Object)(object)val); list.RemoveAt(num2); flag = true; } catch { } } } if (!flag) { break; } } Component[] componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAllImmediate(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAllImmediate(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAllImmediate(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAllImmediate(componentsInChildren); componentsInChildren = (Component[])(object)clone.GetComponentsInChildren(true); DestroyAllImmediate(componentsInChildren); Type type = AccessTools_PhotonViewType(); if (type != null) { DestroyAllImmediate(clone.GetComponentsInChildren(type, true)); } Renderer[] componentsInChildren2 = clone.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { if (kind == ReplayActorKind.Enemy && IsEnemyHelperRenderer(val2)) { val2.enabled = false; val2.forceRenderingOff = true; continue; } val2.enabled = true; val2.forceRenderingOff = false; val2.shadowCastingMode = (ShadowCastingMode)1; ActivateBranch(((Component)val2).transform, clone.transform); } } Animator[] componentsInChildren3 = clone.GetComponentsInChildren(true); foreach (Animator val3 in componentsInChildren3) { if (!((Object)(object)val3 == (Object)null)) { ((Behaviour)val3).enabled = true; val3.cullingMode = (AnimatorCullingMode)0; val3.updateMode = (AnimatorUpdateMode)2; val3.applyRootMotion = false; } } } private static bool IsEnemyHelperRenderer(Renderer renderer) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00b1: 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) string text = ((Object)renderer).name.ToLowerInvariant(); if (text.Contains("vision") || text.Contains("range") || text.Contains("trigger") || text.Contains("debug")) { return true; } if ((Object)(object)((renderer is MeshRenderer) ? renderer : null) == (Object)null) { return false; } MeshFilter component = ((Component)renderer).GetComponent(); if (!(((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) ? ((Object)component.sharedMesh).name.ToLowerInvariant() : string.Empty).Contains("sphere")) { return false; } Bounds bounds = renderer.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(size.x > 2.5f) && !(size.y > 2.5f)) { return size.z > 2.5f; } return true; } private static void DestroyAllImmediate(Component[] components) { if (components == null) { return; } for (int i = 0; i < components.Length; i++) { if (!((Object)(object)components[i] == (Object)null)) { try { Object.DestroyImmediate((Object)(object)components[i]); } catch { } } } } private static void ActivateBranch(Transform leaf, Transform root) { Transform val = leaf; while ((Object)(object)val != (Object)null) { if (!((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } if (!((Object)(object)val == (Object)(object)root)) { val = val.parent; continue; } break; } } private static void SetLayerRecursive(Transform root, int layer) { ((Component)root).gameObject.layer = layer; for (int i = 0; i < root.childCount; i++) { SetLayerRecursive(root.GetChild(i), layer); } } private static Type AccessTools_PhotonViewType() { return AccessTools.TypeByName("Photon.Pun.PhotonView"); } private static GameObject BuildStylized(ReplayActor actor, Transform parent) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0029: 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_0071: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Replay Stylized " + actor.DisplayName); val.transform.SetParent(parent, false); Material material = ReplayMaterials.Ghost(ColorFor(actor.Kind)); switch (actor.Kind) { case ReplayActorKind.Player: AddPart(val.transform, (PrimitiveType)1, new Vector3(0f, 0.9f, 0f), new Vector3(0.5f, 0.7f, 0.5f), material); AddPart(val.transform, (PrimitiveType)0, new Vector3(0f, 1.6f, 0f), new Vector3(0.45f, 0.45f, 0.45f), material); break; case ReplayActorKind.Enemy: AddPart(val.transform, (PrimitiveType)1, new Vector3(0f, 0.7f, 0f), new Vector3(1.1f, 0.8f, 1.1f), material); AddPart(val.transform, (PrimitiveType)0, new Vector3(0f, 1.4f, 0f), new Vector3(0.85f, 0.85f, 0.85f), material); break; default: AddPart(val.transform, (PrimitiveType)3, Vector3.zero, Vector3.one * 0.5f, material); break; } return val; } private static void AddPart(Transform parent, PrimitiveType type, Vector3 localPos, Vector3 scale, Material material) { //IL_0000: 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) GameObject obj = GameObject.CreatePrimitive(type); obj.transform.SetParent(parent, false); obj.transform.localPosition = localPos; obj.transform.localScale = scale; Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)material != (Object)null) { component2.sharedMaterial = material; } } private static Color ColorFor(ReplayActorKind kind) { //IL_0023: 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_004d: 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) return (Color)(kind switch { ReplayActorKind.Player => new Color(0.3f, 0.7f, 1f), ReplayActorKind.Enemy => new Color(1f, 0.3f, 0.25f), ReplayActorKind.Valuable => new Color(1f, 0.85f, 0.3f), _ => new Color(0.7f, 0.7f, 0.7f), }); } } [HarmonyPatch(typeof(LevelGenerator), "Generate")] internal static class ReplayPatchGenerate { private static void Prefix() { string levelName = "Unknown Level"; string levelResource = string.Empty; Level levelCurrent = ReplayAccess.GetLevelCurrent(); if ((Object)(object)levelCurrent != (Object)null) { levelName = levelCurrent.NarrativeName ?? ((Object)levelCurrent).name; levelResource = ((Object)levelCurrent).name; } ReplayController.Instance?.OnLevelGenerateStarting(); int seed = (ReplaySeed.Active ? ReplaySeed.CurrentSeed : ReplaySeed.NewRandomSeed()); if (!ReplayController.IsPlaybackBoot) { ReplaySeed.Activate(seed); } ReplayLayoutCapture.BeginLevel(levelName, levelResource, ReplaySeed.CurrentSeed); } } [HarmonyPatch(typeof(LevelGenerator), "TileGeneration")] internal static class ReplayPatchTileGeneration { private static void Prefix() { ReplaySeed.SeedNextLayoutPhase(); } } [HarmonyPatch(typeof(LevelGenerator), "ModuleGeneration")] internal static class ReplayPatchModuleGeneration { private static void Prefix() { ReplaySeed.SeedNextLayoutPhase(); } } [HarmonyPatch(typeof(LevelGenerator), "GenerateDone")] internal static class ReplayPatchGenerateDone { private static void Postfix() { ReplayController.Instance?.OnLevelGenerateDone(); } } [HarmonyPatch(typeof(RunManager), "ChangeLevel")] internal static class ReplayPatchChangeLevel { private static void Prefix(bool _completedLevel) { ReplayController.Instance?.OnLevelChanging(_completedLevel); } } [HarmonyPatch(typeof(CameraPosition), "Update")] internal static class ReplayPatchCameraPositionUpdate { private static void Postfix(CameraPosition __instance) { ReplayController.Instance?.ApplyCameraPosition(__instance); } } [HarmonyPatch(typeof(CameraAim), "Update")] internal static class ReplayPatchCameraAimUpdate { private static void Postfix(CameraAim __instance) { ReplayController.Instance?.ApplyCameraAim(__instance); } } internal sealed class ReplayGhost { public ReplayActor Actor; public Transform Root; public Renderer[] Renderers; public Animator[] Animators; public Quaternion CurrentAim = Quaternion.identity; public bool HasAim; public Vector3 PreviousPosition; public bool HasPreviousPosition; public ReplayAnimParam[] AnimSchema; public ReplayAnimBinding[] AnimBindings; public float[] AnimWork; public float[] TriggerState; public bool HasRecordedAnim; } internal sealed class ReplayPlayer { private readonly List _ghosts = new List(); private ReplayData _data; private Transform _root; private float _time; private bool _playing; private float _speed = 1f; public bool HasReplay => _data != null; public bool Playing => _playing; public float Time => _time; public float Duration { get { if (_data == null) { return 0f; } return _data.Duration; } } public float Speed { get { return _speed; } set { _speed = Mathf.Clamp(value, 0.1f, 4f); } } public string LevelName { get { if (_data == null) { return string.Empty; } return _data.LevelName; } } public List PlayerGhosts { get { List list = new List(); for (int i = 0; i < _ghosts.Count; i++) { if (_ghosts[i].Actor.Kind == ReplayActorKind.Player) { list.Add(_ghosts[i]); } } return list; } } public ReplayGhost GetDeathHeadGhost() { for (int i = 0; i < _ghosts.Count; i++) { ReplayGhost replayGhost = _ghosts[i]; if (replayGhost.Actor.Kind == ReplayActorKind.Prop && !((Object)(object)replayGhost.Root == (Object)null) && ((Component)replayGhost.Root).gameObject.activeSelf && !string.IsNullOrEmpty(replayGhost.Actor.DisplayName) && replayGhost.Actor.DisplayName.IndexOf("Death Head", StringComparison.OrdinalIgnoreCase) >= 0) { return replayGhost; } } return null; } public void Load(ReplayData data) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Unload(); _data = data; if (_data == null) { return; } GameObject val = new GameObject("Empress Replay Ghosts"); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); _root = val.transform; for (int i = 0; i < _data.Actors.Count; i++) { ReplayActor replayActor = _data.Actors[i]; if (replayActor.Kind != ReplayActorKind.Prop || ActorMoved(replayActor)) { BuildGhost(replayActor); } } _time = 0f; _playing = false; Apply(0f); } public void Unload() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)((Component)_root).gameObject); } _root = null; _ghosts.Clear(); _data = null; _time = 0f; _playing = false; } public void Play() { if (_data != null) { if (_time >= _data.Duration) { _time = 0f; } _playing = true; } } public void Pause() { _playing = false; } public void TogglePlay() { if (_playing) { Pause(); } else { Play(); } } public void Scrub(float normalized) { if (_data != null) { _time = Mathf.Clamp01(normalized) * _data.Duration; Apply(_time); } } public void Step(float seconds) { if (_data != null) { _time = Mathf.Clamp(_time + seconds, 0f, _data.Duration); Apply(_time); } } public void Tick(float deltaTime) { if (_playing && _data != null) { _time += deltaTime * _speed; if (_time >= _data.Duration) { _time = _data.Duration; _playing = false; } Apply(_time); } } private void Apply(float time) { //IL_0091: 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_007d: 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_00bb: Unknown result type (might be due to invalid IL or missing references) float frame = ((_data.TickInterval > 0f) ? (time / _data.TickInterval) : 0f); for (int i = 0; i < _ghosts.Count; i++) { ReplayGhost replayGhost = _ghosts[i]; if (!((Object)(object)replayGhost.Root == (Object)null)) { SampleActor(replayGhost, frame, out var position, out var rotation, out var active, out var aim, out var hasAim, out var loIndex, out var hiIndex, out var blend); ((Component)replayGhost.Root).gameObject.SetActive(active); if (active) { replayGhost.Root.position = position; replayGhost.Root.rotation = rotation; } replayGhost.CurrentAim = aim; replayGhost.HasAim = hasAim; if (replayGhost.HasRecordedAnim) { DriveRecordedAnimation(replayGhost, loIndex, hiIndex, blend, active); } else { UpdatePlayerAnimation(replayGhost, position, active); } } } } private void UpdatePlayerAnimation(ReplayGhost ghost, Vector3 position, bool active) { //IL_0038: 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_003f: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) if (ghost.Actor.Kind != ReplayActorKind.Player || ghost.Animators == null || ghost.Animators.Length == 0) { return; } float num = 0f; if (active && _playing && ghost.HasPreviousPosition) { Vector3 val = position - ghost.PreviousPosition; num = ((Vector3)(ref val)).magnitude / Mathf.Max(Time.deltaTime * Mathf.Max(_speed, 0.1f), 0.016f); } bool flag = active && _playing && num > 0.12f; bool value = flag && num > 4.2f; for (int i = 0; i < ghost.Animators.Length; i++) { Animator val2 = ghost.Animators[i]; if (!((Object)(object)val2 == (Object)null)) { SetBoolIfExists(val2, "Moving", flag); SetBoolIfExists(val2, "Sprinting", value); SetBoolIfExists(val2, "Sliding", value: false); SetBoolIfExists(val2, "Jumping", value: false); SetBoolIfExists(val2, "Falling", value: false); SetBoolIfExists(val2, "Turning", value: false); SetBoolIfExists(val2, "Grabbing", value: false); SetBoolIfExists(val2, "Crouching", value: false); SetBoolIfExists(val2, "Crawling", value: false); SetBoolIfExists(val2, "Tumbling", value: false); SetBoolIfExists(val2, "TumblingMove", value: false); val2.speed = (flag ? Mathf.Clamp(num * 0.35f, 0.8f, 1.8f) : 1f); } } ghost.PreviousPosition = position; ghost.HasPreviousPosition = active; } private static void SetBoolIfExists(Animator animator, string name, bool value) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((Object)(object)animator == (Object)null) { return; } AnimatorControllerParameter[] parameters = animator.parameters; for (int i = 0; i < parameters.Length; i++) { if ((int)parameters[i].type == 4 && parameters[i].name == name) { animator.SetBool(name, value); break; } } } private void SampleActor(ReplayGhost ghost, float frame, out Vector3 position, out Quaternion rotation, out bool active, out Quaternion aim, out bool hasAim, out int loIndex, out int hiIndex, out float blend) { //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_0020: 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) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: 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_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) ReplayActor actor = ghost.Actor; int count = actor.FrameIndices.Count; position = Vector3.zero; rotation = Quaternion.identity; active = false; aim = Quaternion.identity; hasAim = false; loIndex = 0; hiIndex = 0; blend = 0f; if (count == 0) { return; } bool flag = actor.AimRotations.Count == count; if (frame <= (float)actor.FrameIndices[0]) { position = actor.Positions[0]; rotation = actor.Rotations[0]; active = actor.Active[0]; aim = (flag ? actor.AimRotations[0] : rotation); hasAim = flag; return; } if (frame >= (float)actor.FrameIndices[count - 1]) { int num = count - 1; position = actor.Positions[num]; rotation = actor.Rotations[num]; active = actor.Active[num]; aim = (flag ? actor.AimRotations[num] : rotation); hasAim = flag; loIndex = num; hiIndex = num; return; } int num2 = 0; int num3 = count - 1; while (num3 - num2 > 1) { int num4 = num2 + num3 >> 1; if ((float)actor.FrameIndices[num4] <= frame) { num2 = num4; } else { num3 = num4; } } float num5 = actor.FrameIndices[num2]; float num6 = actor.FrameIndices[num3]; float num7 = ((num6 > num5) ? ((frame - num5) / (num6 - num5)) : 0f); position = Vector3.Lerp(actor.Positions[num2], actor.Positions[num3], num7); rotation = Quaternion.Slerp(actor.Rotations[num2], actor.Rotations[num3], num7); active = actor.Active[num2]; aim = (flag ? Quaternion.Slerp(actor.AimRotations[num2], actor.AimRotations[num3], num7) : rotation); hasAim = flag; loIndex = num2; hiIndex = num3; blend = num7; } private void DriveRecordedAnimation(ReplayGhost ghost, int lo, int hi, float blend, bool active) { if (!active || ghost.AnimSchema == null || ghost.AnimWork == null) { return; } ReplayActor actor = ghost.Actor; int count = actor.AnimSamples.Count; if (count == 0) { return; } if (lo < 0 || lo >= count) { lo = Mathf.Clamp(lo, 0, count - 1); } if (hi < 0 || hi >= count) { hi = Mathf.Clamp(hi, 0, count - 1); } float[] array = actor.AnimSamples[lo]; float[] array2 = actor.AnimSamples[hi]; for (int i = 0; i < ghost.AnimSchema.Length; i++) { float num = ((i < array.Length) ? array[i] : 0f); if (ghost.AnimSchema[i].Type == ReplayAnimParamType.Float) { float num2 = ((i < array2.Length) ? array2[i] : num); ghost.AnimWork[i] = Mathf.Lerp(num, num2, blend); } else { ghost.AnimWork[i] = num; } } float num3 = ((lo < actor.AnimSpeeds.Count) ? actor.AnimSpeeds[lo] : 1f); float num4 = ((hi < actor.AnimSpeeds.Count) ? actor.AnimSpeeds[hi] : num3); float speed = Mathf.Lerp(num3, num4, blend); ReplayAnimation.Apply(ghost.AnimBindings, ghost.AnimSchema, ghost.AnimWork, speed, ghost.TriggerState); } public static bool ActorMoved(ReplayActor actor) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_003d: 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_0043: 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_005e: 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_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) int count = actor.Positions.Count; if (count < 2) { return false; } Vector3 val = actor.Positions[0]; Vector3 val2 = actor.Positions[0]; for (int i = 1; i < count; i++) { val = Vector3.Min(val, actor.Positions[i]); val2 = Vector3.Max(val2, actor.Positions[i]); } Vector3 val3 = val2 - val; return ((Vector3)(ref val3)).sqrMagnitude > 0.02f; } private void BuildGhost(ReplayActor actor) { GameObject val = ReplayModelFactory.CreateActorModel(actor, _root); ReplayGhost replayGhost = new ReplayGhost { Actor = actor, Root = val.transform, Renderers = val.GetComponentsInChildren(true), Animators = val.GetComponentsInChildren(true) }; if (actor.HasAnim && actor.AnimParams.Count > 0 && actor.AnimSamples.Count == actor.FrameIndices.Count) { ReplayAnimParam[] array = actor.AnimParams.ToArray(); ReplayAnimBinding[] array2 = ReplayAnimation.BuildBindings(replayGhost.Animators, array); if (array2 != null) { replayGhost.AnimSchema = array; replayGhost.AnimBindings = array2; replayGhost.AnimWork = new float[array.Length]; replayGhost.TriggerState = new float[array.Length]; replayGhost.HasRecordedAnim = true; } } _ghosts.Add(replayGhost); } } internal sealed class ReplayRecorder { private sealed class TrackedActor { public ReplayActor Data; public Transform Transform; public Vector3 LastPosition; public Quaternion LastRotation; public bool HasLast; public bool CaptureAim; public Quaternion LastAim; public bool HasLastAim; public PlayerAvatar Avatar; public Animator Animator; public ReplayAnimParam[] AnimSchema; public float[] AnimValues; public float[] LastAnimValues; public float AnimSpeed = 1f; public float LastAnimSpeed = 1f; public bool HasAnimLast; } private readonly Dictionary _tracked = new Dictionary(); private ReplayData _data; private float _tickTimer; private int _frame; private bool _recording; private float _rescanTimer; private float _moduleSettleTimer; public bool Recording => _recording; public int FrameCount => _frame; public void Begin() { _data = new ReplayData { LevelName = ReplayLayoutCapture.LevelName, LevelResourceName = ReplayLayoutCapture.LevelResource, LevelSeed = ReplayLayoutCapture.LevelSeed, LevelsCompleted = ReplayAccess.GetLevelsCompleted(), TickInterval = EmpressReplaysPlugin.Settings.TickInterval.Value, RecordedAt = DateTime.Now }; _tracked.Clear(); _frame = 0; _tickTimer = 0f; _rescanTimer = 0f; _moduleSettleTimer = 8f; _recording = true; ReplayAccess.CaptureGeneratedModules(_data.Modules); ScanActors(); } public ReplayData End() { if (_data == null) { return null; } _recording = false; _data.FrameCount = _frame; _data.Duration = (float)_frame * _data.TickInterval; ReplayData data = _data; _data = null; _tracked.Clear(); return data; } public void Tick(float deltaTime) { if (!_recording || _data == null) { return; } _rescanTimer -= deltaTime; if (_rescanTimer <= 0f) { _rescanTimer = 1f; ScanActors(); if (_moduleSettleTimer > 0f) { ReplayAccess.CaptureGeneratedModules(_data.Modules); } } _moduleSettleTimer -= deltaTime; _tickTimer -= deltaTime; if (!(_tickTimer > 0f)) { _tickTimer = _data.TickInterval; CaptureFrame(); _frame++; } } private void CaptureFrame() { //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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair item in _tracked) { TrackedActor value = item.Value; if (!((Object)(object)value.Transform != (Object)null) || !((Component)value.Transform).gameObject.activeInHierarchy || ((Object)(object)value.Avatar != (Object)null && ReplayAccess.IsAvatarDead(value.Avatar))) { if (value.HasLast) { AppendSample(value, value.LastPosition, value.LastRotation, active: false, value.LastAim); value.HasLast = false; } continue; } Vector3 position = value.Transform.position; Quaternion rotation = value.Transform.rotation; Quaternion val = value.LastAim; bool flag = false; if (value.CaptureAim) { val = ReplayAccess.GetLocalAimRotation(); flag = !value.HasLastAim || Quaternion.Angle(val, value.LastAim) > 0.5f; } bool flag2 = false; if (value.Data.HasAnim && (Object)(object)value.Animator != (Object)null && value.AnimSchema != null) { value.AnimSpeed = ReplayAnimation.Snapshot(value.Animator, value.AnimSchema, value.AnimValues); flag2 = !value.HasAnimLast || ReplayAnimation.Changed(value.AnimSchema, value.AnimValues, value.LastAnimValues, value.AnimSpeed, value.LastAnimSpeed); } int num; if (value.HasLast) { Vector3 val2 = position - value.LastPosition; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0004f)) { num = ((Quaternion.Angle(rotation, value.LastRotation) > 0.5f) ? 1 : 0); goto IL_0198; } } num = 1; goto IL_0198; IL_0198: if (((uint)num | (flag ? 1u : 0u) | (flag2 ? 1u : 0u)) != 0 || _frame == 0) { AppendSample(value, position, rotation, active: true, val); value.LastPosition = position; value.LastRotation = rotation; value.HasLast = true; if (value.CaptureAim) { value.LastAim = val; value.HasLastAim = true; } if (value.Data.HasAnim && value.AnimSchema != null) { Array.Copy(value.AnimValues, value.LastAnimValues, value.AnimValues.Length); value.LastAnimSpeed = value.AnimSpeed; value.HasAnimLast = true; } } } } private void AppendSample(TrackedActor tracked, Vector3 position, Quaternion rotation, bool active, Quaternion aim) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) tracked.Data.FrameIndices.Add(_frame); tracked.Data.Positions.Add(position); tracked.Data.Rotations.Add(rotation); tracked.Data.Active.Add(active); if (tracked.CaptureAim) { tracked.Data.AimRotations.Add(aim); } if (tracked.Data.HasAnim && tracked.AnimValues != null) { float[] array = new float[tracked.AnimValues.Length]; Array.Copy(tracked.AnimValues, array, array.Length); tracked.Data.AnimSamples.Add(array); tracked.Data.AnimSpeeds.Add(tracked.AnimSpeed); } } private void ScanActors() { PlayerAvatar localAvatar = ReplayAccess.GetLocalAvatar(); List playerList = ReplayAccess.GetPlayerList(); if (playerList != null) { for (int i = 0; i < playerList.Count; i++) { PlayerAvatar val = playerList[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.photonView == (Object)null)) { int num = HashId(ReplayActorKind.Player, val.photonView.ViewID); if (!_tracked.ContainsKey(num)) { Track(num, ReplayActorKind.Player, ReplayAccess.GetPlayerName(val), ((Component)val).transform, string.Empty, (Object)(object)val == (Object)(object)localAvatar, ReplayAccess.GetAvatarAnimator(val), val); } } } } List spawnedEnemies = ReplayAccess.GetSpawnedEnemies(); if (spawnedEnemies != null) { for (int j = 0; j < spawnedEnemies.Count; j++) { EnemyParent val2 = spawnedEnemies[j]; if ((Object)(object)val2 == (Object)null) { continue; } Transform enemyTransform = ReplayAccess.GetEnemyTransform(val2); if (!((Object)(object)enemyTransform == (Object)null)) { int num2 = HashId(ReplayActorKind.Enemy, ((Object)enemyTransform).GetInstanceID()); if (!_tracked.ContainsKey(num2)) { Track(num2, ReplayActorKind.Enemy, ReplayAccess.GetEnemyName(val2), enemyTransform, CleanName(((Object)((Component)val2).gameObject).name), isLocalPlayer: false, ReplayAccess.GetEnemyAnimator(enemyTransform), null); } } } } ValuableObject[] array = Object.FindObjectsOfType(); foreach (ValuableObject val3 in array) { if (!((Object)(object)val3 == (Object)null)) { int num3 = HashId(ReplayActorKind.Valuable, ((Object)val3).GetInstanceID()); if (!_tracked.ContainsKey(num3)) { Track(num3, ReplayActorKind.Valuable, CleanName(((Object)val3).name), ((Component)val3).transform, CleanName(((Object)val3).name), isLocalPlayer: false, null, null); } } } PhysGrabObject[] array2 = Object.FindObjectsOfType(); foreach (PhysGrabObject val4 in array2) { if (!((Object)(object)val4 == (Object)null) && !((Object)(object)((Component)val4).GetComponentInParent() != (Object)null)) { int num4 = HashId(ReplayActorKind.Prop, ((Object)val4).GetInstanceID()); if (!_tracked.ContainsKey(num4)) { Track(num4, ReplayActorKind.Prop, CleanName(((Object)val4).name), ((Component)val4).transform, CleanName(((Object)val4).name), isLocalPlayer: false, null, null); } } } } private void Track(int id, ReplayActorKind kind, string name, Transform transform, string prefabHint, bool isLocalPlayer, Animator animator, PlayerAvatar avatar) { //IL_003f: 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_0044: Unknown result type (might be due to invalid IL or missing references) ReplayActor replayActor = new ReplayActor { ActorId = id, Kind = kind, DisplayName = name, PrefabPath = (prefabHint ?? string.Empty), BaseScale = (((Object)(object)transform != (Object)null) ? transform.lossyScale : Vector3.one), IsLocalPlayer = isLocalPlayer }; _data.Actors.Add(replayActor); TrackedActor trackedActor = new TrackedActor { Data = replayActor, Transform = transform, HasLast = false, CaptureAim = isLocalPlayer, Avatar = avatar }; ReplayAnimParam[] array = ReplayAnimation.BuildSchema(animator); if (array != null && array.Length != 0) { replayActor.HasAnim = true; replayActor.AnimParams.AddRange(array); trackedActor.Animator = animator; trackedActor.AnimSchema = array; trackedActor.AnimValues = new float[array.Length]; trackedActor.LastAnimValues = new float[array.Length]; } _tracked[id] = trackedActor; } private static int HashId(ReplayActorKind kind, int raw) { return (int)((uint)kind << 28) ^ (raw & 0xFFFFFFF); } private static string CleanName(string raw) { if (string.IsNullOrEmpty(raw)) { return "Object"; } return raw.Replace("(Clone)", string.Empty).Replace("Valuable ", string.Empty).Trim(); } } internal static class ReplaySeed { private static Random _layoutStream; public static bool Active { get; private set; } public static int CurrentSeed { get; private set; } public static void Activate(int seed) { CurrentSeed = seed; _layoutStream = new Random(seed); Active = true; } public static void Deactivate() { Active = false; _layoutStream = null; } public static void SeedNextLayoutPhase() { if (Active && _layoutStream != null) { Random.InitState(_layoutStream.Next()); } } public static int NewRandomSeed() { return Guid.NewGuid().GetHashCode(); } } }