Decompiled source of Y4NGZInteractions v1.0.1

Y4NGZInteractions.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Y4NGZInteractions.InteractionAnimationApi;
using Y4NGZInteractions.InteractionAnimationApi.Authoring;
using Y4NGZInteractions.InteractionAnimationApi.Presenters;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Y4NGZInteractions.Tests")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Y4NGZInteractions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Consumer-agnostic local animation presentation API for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("Y4NGZInteractions")]
[assembly: AssemblyTitle("Y4NGZInteractions")]
[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 Y4NGZInteractions
{
	internal sealed class InteractionRuntimeHost : MonoBehaviour
	{
		private Harmony harmony;

		private ManualLogSource log;

		private bool applicationQuitting;

		private bool tornDown;

		internal void Initialize(Harmony harmony, ManualLogSource log)
		{
			this.harmony = harmony;
			this.log = log;
			Application.quitting += OnApplicationQuitting;
		}

		private void LateUpdate()
		{
			InteractionAnimationApiRestoreDiagnostics.BeginCoordinatorLateUpdateTick();
			try
			{
				InteractionAnimationApiPlugin.Tick(Time.deltaTime);
			}
			finally
			{
				InteractionAnimationApiRestoreDiagnostics.EndCoordinatorLateUpdateTick();
			}
		}

		private void OnApplicationQuit()
		{
			applicationQuitting = true;
		}

		private void OnApplicationQuitting()
		{
			applicationQuitting = true;
			TearDown();
		}

		private void OnDestroy()
		{
			Application.quitting -= OnApplicationQuitting;
			if (!applicationQuitting)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogError((object)("Y4NGZInteractions runtime host destroyed outside application shutdown " + string.Format("(frame={0}, host='{1}'). ", Time.frameCount, ((Object)(object)((Component)this).gameObject != (Object)null) ? ((Object)((Component)this).gameObject).name : "<null>") + "The interaction animation API and all Harmony patches are going down with it."));
				}
			}
			TearDown();
		}

		private void TearDown()
		{
			if (tornDown)
			{
				return;
			}
			tornDown = true;
			try
			{
				InteractionAnimationApiPlugin.Shutdown();
				InteractionAnimationApiRestoreDiagnostics.Shutdown();
			}
			catch (Exception ex)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogWarning((object)("Y4NGZInteractions shutdown warning: " + ex.Message));
				}
			}
			Harmony obj2 = harmony;
			if (obj2 != null)
			{
				obj2.UnpatchSelf();
			}
		}
	}
	[BepInPlugin("com.y4ngz.interactions", "Y4NGZInteractions", "1.0.1")]
	internal sealed class Plugin : BaseUnityPlugin
	{
		internal const string Guid = "com.y4ngz.interactions";

		internal const string Name = "Y4NGZInteractions";

		internal const string Version = "1.0.1";

		internal const string HostObjectName = "Y4NGZInteractions_Host";

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static InteractionRuntimeHost Host { get; private set; }

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony harmony = new Harmony("com.y4ngz.interactions");
			GameObject val = new GameObject("Y4NGZInteractions_Host")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			Host = val.AddComponent<InteractionRuntimeHost>();
			Host.Initialize(harmony, ((BaseUnityPlugin)this).Logger);
			InitializeModule("Interaction Animation API", delegate
			{
				InteractionAnimationApiPlugin.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			});
			InitializeModule("Interaction Animation API Restoration", delegate
			{
				InteractionAnimationApiRestoreDiagnostics.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			});
			InitializeModule("Interaction Animation API Spawn Hooks", delegate
			{
				harmony.PatchAll();
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Y4NGZInteractions v1.0.1 loaded.");
		}

		private void InitializeModule(string label, Action initialize)
		{
			try
			{
				initialize();
				((BaseUnityPlugin)this).Logger.LogInfo((object)(label + " initialized."));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"{label} initialization failed: {arg}");
			}
		}
	}
	internal static class BuildVersion
	{
		internal const string Value = "1.0.1";
	}
}
namespace Y4NGZInteractions.InteractionAnimationApi
{
	internal static class InteractionAnimationApiPlugin
	{
		private static ManualLogSource logger;

		private static InteractionAnimationCoordinator coordinator;

		private static bool initialized;

		internal static void Initialize(ConfigFile config, ManualLogSource log)
		{
			if (!initialized)
			{
				logger = log;
				coordinator = new InteractionAnimationCoordinator(logger);
				LCInteractionAnimationAPI.Initialize(coordinator);
				initialized = true;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)"[LCInteractionAnimationAPI] api.initialized: standalone local presentation API ready.");
				}
			}
		}

		internal static void Tick(float deltaTime)
		{
			if (initialized)
			{
				coordinator?.Tick(deltaTime);
			}
		}

		internal static void Shutdown()
		{
			if (initialized)
			{
				coordinator?.Shutdown();
				LiveBodyAnimatorPresenter.ShutdownBundleCache();
				LCInteractionAnimationAPI.Shutdown();
				coordinator = null;
				initialized = false;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)"[LCInteractionAnimationAPI] api.shutdown: restoration complete.");
				}
				logger = null;
			}
		}
	}
	internal enum AnimatorStateRestoreMode
	{
		Fresh,
		Crossfade,
		Replay
	}
	internal sealed class AnimatorStateSnapshot
	{
		private readonly struct LayerSnapshot
		{
			public readonly int FullPathHash;

			public readonly float NormalizedTime;

			public readonly float Weight;

			public readonly bool InTransition;

			public LayerSnapshot(int fullPathHash, float normalizedTime, float weight, bool inTransition)
			{
				FullPathHash = fullPathHash;
				NormalizedTime = normalizedTime;
				Weight = weight;
				InTransition = inTransition;
			}
		}

		private readonly struct ParameterSnapshot
		{
			private readonly int nameHash;

			private readonly AnimatorControllerParameterType type;

			private readonly bool boolValue;

			private readonly int intValue;

			private readonly float floatValue;

			private ParameterSnapshot(int nameHash, AnimatorControllerParameterType type, bool boolValue, int intValue, float floatValue)
			{
				//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)
				this.nameHash = nameHash;
				this.type = type;
				this.boolValue = boolValue;
				this.intValue = intValue;
				this.floatValue = floatValue;
			}

			public static ParameterSnapshot Capture(Animator animator, AnimatorControllerParameter parameter)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: 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_001f: Expected I4, but got Unknown
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: 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_0028: Unknown result type (might be due to invalid IL or missing references)
				AnimatorControllerParameterType val = parameter.type;
				return (val - 1) switch
				{
					3 => new ParameterSnapshot(parameter.nameHash, parameter.type, animator.GetBool(parameter.nameHash), 0, 0f), 
					2 => new ParameterSnapshot(parameter.nameHash, parameter.type, boolValue: false, animator.GetInteger(parameter.nameHash), 0f), 
					0 => new ParameterSnapshot(parameter.nameHash, parameter.type, boolValue: false, 0, animator.GetFloat(parameter.nameHash)), 
					_ => new ParameterSnapshot(parameter.nameHash, parameter.type, boolValue: false, 0, 0f), 
				};
			}

			public void Restore(Animator animator)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: 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_001f: Expected I4, but got Unknown
				AnimatorControllerParameterType val = type;
				switch (val - 1)
				{
				case 3:
					animator.SetBool(nameHash, boolValue);
					break;
				case 2:
					animator.SetInteger(nameHash, intValue);
					break;
				case 0:
					animator.SetFloat(nameHash, floatValue);
					break;
				case 1:
					break;
				}
			}
		}

		private const float CrossfadeDurationSeconds = 0.12f;

		private readonly LayerSnapshot[] layers;

		private readonly ParameterSnapshot[] parameters;

		public RuntimeAnimatorController RuntimeAnimatorController { get; }

		public float Speed { get; }

		public bool? CapturedCrouching { get; set; }

		private AnimatorStateSnapshot(RuntimeAnimatorController runtimeAnimatorController, float speed, LayerSnapshot[] layers, ParameterSnapshot[] parameters)
		{
			RuntimeAnimatorController = runtimeAnimatorController;
			Speed = speed;
			this.layers = layers ?? Array.Empty<LayerSnapshot>();
			this.parameters = parameters ?? Array.Empty<ParameterSnapshot>();
		}

		public static AnimatorStateSnapshot Capture(Animator animator)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)animator == (Object)null)
			{
				return null;
			}
			try
			{
				RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
				float speed = animator.speed;
				if (!animator.isInitialized)
				{
					return new AnimatorStateSnapshot(runtimeAnimatorController, speed, Array.Empty<LayerSnapshot>(), Array.Empty<ParameterSnapshot>());
				}
				int num = Math.Max(0, animator.layerCount);
				LayerSnapshot[] array = new LayerSnapshot[num];
				for (int i = 0; i < num; i++)
				{
					AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(i);
					array[i] = new LayerSnapshot(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime, animator.GetLayerWeight(i), animator.IsInTransition(i));
				}
				AnimatorControllerParameter[] array2 = animator.parameters ?? Array.Empty<AnimatorControllerParameter>();
				ParameterSnapshot[] array3 = new ParameterSnapshot[array2.Length];
				for (int j = 0; j < array2.Length; j++)
				{
					AnimatorControllerParameter parameter = array2[j];
					array3[j] = ParameterSnapshot.Capture(animator, parameter);
				}
				return new AnimatorStateSnapshot(runtimeAnimatorController, speed, array, array3);
			}
			catch
			{
				return null;
			}
		}

		public int ReapplyParameters(Animator animator)
		{
			if ((Object)(object)animator == (Object)null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < parameters.Length; i++)
			{
				try
				{
					parameters[i].Restore(animator);
					num++;
				}
				catch
				{
				}
			}
			return num;
		}

		public bool TryReapplyLayerState(Animator animator, int layerIndex)
		{
			if ((Object)(object)animator == (Object)null || layerIndex < 0 || layerIndex >= layers.Length || layerIndex >= animator.layerCount)
			{
				return false;
			}
			try
			{
				LayerSnapshot layerSnapshot = layers[layerIndex];
				if (layerSnapshot.InTransition || layerSnapshot.FullPathHash == 0 || !animator.HasState(layerIndex, layerSnapshot.FullPathHash))
				{
					return false;
				}
				animator.SetLayerWeight(layerIndex, layerSnapshot.Weight);
				animator.Play(layerSnapshot.FullPathHash, layerIndex, layerSnapshot.NormalizedTime);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public bool Restore(Animator animator)
		{
			return Restore(animator, RuntimeAnimatorController);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController)
		{
			return Restore(animator, expectedCurrentController, rebindAnimator: true);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController, bool rebindAnimator)
		{
			return Restore(animator, expectedCurrentController, rebindAnimator, AnimatorStateRestoreMode.Replay);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController, bool rebindAnimator, AnimatorStateRestoreMode restoreMode)
		{
			return Restore(animator, expectedCurrentController, rebindAnimator, restoreMode, null, restoreBaseLayerState: true);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController, bool rebindAnimator, AnimatorStateRestoreMode restoreMode, Action syncParametersBeforeStateReplay, bool restoreBaseLayerState)
		{
			if ((Object)(object)animator == (Object)null)
			{
				return false;
			}
			try
			{
				if ((Object)(object)expectedCurrentController != (Object)null && (Object)(object)animator.runtimeAnimatorController != (Object)(object)expectedCurrentController)
				{
					return false;
				}
				animator.runtimeAnimatorController = RuntimeAnimatorController;
				if (rebindAnimator)
				{
					animator.Rebind();
				}
				animator.speed = Speed;
				for (int i = 0; i < parameters.Length; i++)
				{
					parameters[i].Restore(animator);
				}
				if (syncParametersBeforeStateReplay != null)
				{
					try
					{
						syncParametersBeforeStateReplay();
					}
					catch
					{
					}
				}
				int num = Math.Min(animator.layerCount, layers.Length);
				for (int j = 0; j < num; j++)
				{
					LayerSnapshot layerSnapshot = layers[j];
					animator.SetLayerWeight(j, layerSnapshot.Weight);
					if ((j != 0 || restoreBaseLayerState) && layerSnapshot.FullPathHash != 0)
					{
						switch (restoreMode)
						{
						case AnimatorStateRestoreMode.Crossfade:
							animator.CrossFadeInFixedTime(layerSnapshot.FullPathHash, 0.12f, j, Mathf.Repeat(layerSnapshot.NormalizedTime, 1f));
							break;
						case AnimatorStateRestoreMode.Replay:
							animator.Play(layerSnapshot.FullPathHash, j, layerSnapshot.NormalizedTime);
							break;
						}
					}
				}
				animator.Update(0f);
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
	internal static class InteractionAnimationAssetPathResolver
	{
		internal const string RootMissingReason = "pack_asset_root_missing";

		internal const string PathEscapesRootReason = "asset_bundle_path_escapes_root";

		internal static bool TryNormalizeAssetRoot(string assetRootPath, out string normalizedRoot, out string reason)
		{
			normalizedRoot = string.Empty;
			reason = string.Empty;
			if (string.IsNullOrWhiteSpace(assetRootPath))
			{
				reason = "pack_asset_root_missing";
				return false;
			}
			try
			{
				normalizedRoot = TrimEndingDirectorySeparators(Path.GetFullPath(assetRootPath.Trim()));
			}
			catch (Exception ex)
			{
				reason = "pack_asset_root_invalid:" + ex.GetType().Name;
				normalizedRoot = string.Empty;
				return false;
			}
			if (!Directory.Exists(normalizedRoot))
			{
				reason = "pack_asset_root_missing:" + normalizedRoot;
				normalizedRoot = string.Empty;
				return false;
			}
			return true;
		}

		internal static bool TryResolveBundlePath(string bundleFileName, string normalizedAssetRoot, out string resolvedPath, out string reason)
		{
			resolvedPath = string.Empty;
			reason = string.Empty;
			if (string.IsNullOrWhiteSpace(bundleFileName))
			{
				reason = "asset_bundle_file_empty";
				return false;
			}
			if (string.IsNullOrWhiteSpace(normalizedAssetRoot))
			{
				reason = "pack_asset_root_missing";
				return false;
			}
			try
			{
				string text = (Path.IsPathRooted(bundleFileName) ? Path.GetFullPath(bundleFileName) : Path.GetFullPath(Path.Combine(normalizedAssetRoot, bundleFileName)));
				if (!IsWithinRoot(normalizedAssetRoot, text))
				{
					reason = "asset_bundle_path_escapes_root:" + bundleFileName;
					return false;
				}
				resolvedPath = text;
				return true;
			}
			catch (Exception ex)
			{
				reason = "asset_bundle_path_invalid:" + ex.GetType().Name;
				return false;
			}
		}

		private static bool IsWithinRoot(string normalizedRoot, string candidate)
		{
			string text = TrimEndingDirectorySeparators(Path.GetFullPath(normalizedRoot));
			string fullPath = Path.GetFullPath(candidate);
			if (string.Equals(text, fullPath, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return fullPath.StartsWith(text + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
		}

		private static string TrimEndingDirectorySeparators(string path)
		{
			string text = Path.GetPathRoot(path) ?? string.Empty;
			while (path.Length > text.Length && (path[path.Length - 1] == Path.DirectorySeparatorChar || path[path.Length - 1] == Path.AltDirectorySeparatorChar))
			{
				path = path.Substring(0, path.Length - 1);
			}
			return path;
		}
	}
	internal delegate bool InteractionAnimationBodyOwnershipValidator(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, InteractionAnimationHandle[] conflicts, out string reason);
	internal sealed class InteractionAnimationCoordinator
	{
		private readonly ManualLogSource logger;

		private readonly Func<InteractionAnimationPresentationKind, IInteractionPresenter> presenterFactory;

		private readonly Func<PlayerControllerB> localPlayerResolver;

		private readonly InteractionAnimationBodyOwnershipValidator bodyOwnershipValidator;

		private readonly Func<InteractionAnimationContext, IInteractionPresenter, InteractionAnimationSession> sessionFactory;

		private readonly Dictionary<string, RegisteredPackSnapshot> packs = new Dictionary<string, RegisteredPackSnapshot>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<InteractionAnimationHandle, InteractionAnimationSession> activeSessions = new Dictionary<InteractionAnimationHandle, InteractionAnimationSession>();

		private readonly InteractionAnimationResourceLeaseRegistry leases = new InteractionAnimationResourceLeaseRegistry();

		internal InteractionAnimationCoordinator(ManualLogSource logger, Func<InteractionAnimationPresentationKind, IInteractionPresenter> presenterFactory = null, Func<PlayerControllerB> localPlayerResolver = null, InteractionAnimationBodyOwnershipValidator bodyOwnershipValidator = null, Func<InteractionAnimationContext, IInteractionPresenter, InteractionAnimationSession> sessionFactory = null)
		{
			this.logger = logger;
			this.presenterFactory = presenterFactory ?? new Func<InteractionAnimationPresentationKind, IInteractionPresenter>(CreateDefaultPresenter);
			this.localPlayerResolver = localPlayerResolver ?? new Func<PlayerControllerB>(ResolveDefaultLocalPlayer);
			this.bodyOwnershipValidator = bodyOwnershipValidator ?? new InteractionAnimationBodyOwnershipValidator(TryValidateBodyAnimatorOwnership);
			this.sessionFactory = sessionFactory ?? ((Func<InteractionAnimationContext, IInteractionPresenter, InteractionAnimationSession>)((InteractionAnimationContext context, IInteractionPresenter presenter) => new InteractionAnimationSession(context, presenter)));
		}

		internal bool TryRegisterInteractionPack(InteractionAnimationPackDefinition pack, out string reason)
		{
			RegisteredPackSnapshot snapshot;
			InteractionAnimationValidationReport interactionAnimationValidationReport = InteractionAnimationPackValidator.Validate(pack, out snapshot);
			reason = InteractionAnimationManifestValidator.GetFirstErrorCode(interactionAnimationValidationReport);
			if (!interactionAnimationValidationReport.IsValid)
			{
				return false;
			}
			if (packs.ContainsKey(snapshot.PackId))
			{
				reason = "pack_already_registered";
				return false;
			}
			packs.Add(snapshot.PackId, snapshot);
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] pack.registered: pack='" + snapshot.PackId + "' version='" + snapshot.Version + "' " + $"interactions={snapshot.InteractionCount}."));
			}
			return true;
		}

		internal bool TryStartInteraction(InteractionAnimationRequest request, out InteractionAnimationHandle handle, out string reason)
		{
			handle = InteractionAnimationHandle.Empty;
			if (!TryResolveRequest(request, out var pack, out var interaction, out reason))
			{
				return false;
			}
			PlayerControllerB val = ResolveLocalPlayer();
			bool flag = request.Player == val;
			if (interaction.PresentationKind == InteractionAnimationPresentationKind.DedicatedLocalViewmodel && !flag)
			{
				reason = "dedicated_viewmodel_requires_local_player";
				return false;
			}
			InteractionAnimationResourceClaim[] claims = BuildClaims(request.Player, interaction.PresentationKind, flag);
			if (!leases.TryPlanAcquisition(claims, request.ConflictPolicy, out var conflicts, out reason))
			{
				return false;
			}
			if (!bodyOwnershipValidator(request.Player, interaction.PresentationKind, conflicts, out reason))
			{
				return false;
			}
			handle = InteractionAnimationHandle.NewHandle();
			InteractionAnimationRequest request2 = new InteractionAnimationRequest
			{
				Player = request.Player,
				PackId = pack.PackId,
				InteractionId = interaction.InteractionId,
				ConflictPolicy = request.ConflictPolicy
			};
			InteractionAnimationContext arg = new InteractionAnimationContext(handle, request2, interaction.CreateDefinition(), interaction.Manifest, pack.AssetRootPath, logger);
			IInteractionPresenter arg2 = CreatePresenter(interaction.PresentationKind);
			InteractionAnimationSession interactionAnimationSession = sessionFactory(arg, arg2);
			if (!interactionAnimationSession.TryPreflight(out reason))
			{
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			InteractionAnimationSession[] suspended = Array.Empty<InteractionAnimationSession>();
			if (conflicts.Length != 0 && !TrySuspendConflicts(conflicts, out suspended, out reason))
			{
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			if (!leases.TryAcquire(handle, claims, out reason))
			{
				ResumeConflicts(suspended);
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			if (!interactionAnimationSession.TryStart(out reason))
			{
				leases.Release(handle);
				ResumeConflicts(suspended);
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			FinalizeConflicts(suspended);
			activeSessions.Add(handle, interactionAnimationSession);
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] interaction.started: " + $"handle={handle} pack='{pack.PackId}' interaction='{interaction.InteractionId}' " + $"presentation='{interaction.PresentationKind}'."));
			}
			return true;
		}

		internal bool TryPreloadInteractionAssets(string packId, string interactionId, out string reason)
		{
			reason = string.Empty;
			if (string.IsNullOrWhiteSpace(packId) || string.IsNullOrWhiteSpace(interactionId))
			{
				reason = "preload_invalid_identity";
				return false;
			}
			if (!packs.TryGetValue(packId, out var value))
			{
				reason = "pack_not_registered";
				return false;
			}
			if (!value.TryGetInteraction(interactionId, out var interaction))
			{
				reason = "interaction_not_registered";
				return false;
			}
			if (interaction.PresentationKind == InteractionAnimationPresentationKind.BodyWorld)
			{
				return LiveBodyAnimatorPresenter.TryPreloadBundles(interaction.Manifest, value.AssetRootPath, logger, out reason);
			}
			return LocalViewmodelPresenter.TryBeginPreload(interaction.Manifest, value.AssetRootPath, logger, out reason);
		}

		internal bool TryStopInteraction(InteractionAnimationHandle handle, InteractionAnimationStopReason reason)
		{
			if (!activeSessions.TryGetValue(handle, out var value))
			{
				return false;
			}
			if (!value.TryStopAndRestore(reason))
			{
				return false;
			}
			leases.Release(handle);
			activeSessions.Remove(handle);
			NotifyEnded(value, reason);
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] interaction.stopped: " + $"handle={handle} reason='{reason}'."));
			}
			return true;
		}

		internal bool IsInteractionActive(InteractionAnimationHandle handle)
		{
			if (activeSessions.TryGetValue(handle, out var value))
			{
				return value.IsActive;
			}
			return false;
		}

		internal bool TryGetActiveInteraction(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, out InteractionAnimationHandle handle)
		{
			handle = InteractionAnimationHandle.Empty;
			if (player == null)
			{
				return false;
			}
			foreach (KeyValuePair<InteractionAnimationHandle, InteractionAnimationSession> activeSession in activeSessions)
			{
				if (activeSession.Value.IsActive && activeSession.Value.Player == player && activeSession.Value.PresentationKind == presentationKind)
				{
					handle = activeSession.Key;
					return true;
				}
			}
			return false;
		}

		internal bool TrySetInteractionAnimatorParameter(InteractionAnimationHandle handle, string parameterName, AnimatorControllerParameterType parameterType, float value)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (activeSessions.TryGetValue(handle, out var value2))
			{
				return value2.TrySetAnimatorParameter(parameterName, parameterType, value);
			}
			return false;
		}

		internal bool TryBeginInteractionExit(InteractionAnimationHandle handle, out string reason)
		{
			reason = string.Empty;
			if (!activeSessions.TryGetValue(handle, out var value) || !value.IsActive)
			{
				reason = "interaction_not_active";
				return false;
			}
			float num = value.BeginExit();
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] interaction.exit_begun: " + $"handle={handle} exitSeconds={num:0.###}."));
			}
			return true;
		}

		internal void Tick(float deltaTime)
		{
			if (activeSessions.Count == 0)
			{
				return;
			}
			InteractionAnimationHandle[] array = activeSessions.Keys.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (activeSessions.TryGetValue(array[i], out var value))
				{
					InteractionAnimationStopReason? interactionAnimationStopReason = value.Tick(deltaTime);
					if (interactionAnimationStopReason.HasValue)
					{
						TryStopInteraction(array[i], interactionAnimationStopReason.Value);
					}
				}
			}
		}

		internal void Shutdown()
		{
			InteractionAnimationHandle[] array = activeSessions.Keys.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				TryStopInteraction(array[i], InteractionAnimationStopReason.Shutdown);
			}
			leases.Clear();
			packs.Clear();
		}

		private bool TryResolveRequest(InteractionAnimationRequest request, out RegisteredPackSnapshot pack, out RegisteredInteractionSnapshot interaction, out string reason)
		{
			pack = null;
			interaction = null;
			reason = string.Empty;
			if (request == null)
			{
				reason = "request_null";
				return false;
			}
			if (request.Player == null)
			{
				reason = "request_player_missing";
				return false;
			}
			if (string.IsNullOrWhiteSpace(request.PackId))
			{
				reason = "request_pack_id_empty";
				return false;
			}
			if (string.IsNullOrWhiteSpace(request.InteractionId))
			{
				reason = "request_interaction_id_empty";
				return false;
			}
			if (!Enum.IsDefined(typeof(InteractionAnimationConflictPolicy), request.ConflictPolicy))
			{
				reason = "request_conflict_policy_invalid";
				return false;
			}
			if (!packs.TryGetValue(request.PackId, out pack))
			{
				reason = "pack_not_registered";
				return false;
			}
			if (!pack.TryGetInteraction(request.InteractionId, out interaction))
			{
				reason = "interaction_not_registered";
				return false;
			}
			return true;
		}

		private bool TryValidateBodyAnimatorOwnership(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, InteractionAnimationHandle[] conflicts, out string reason)
		{
			reason = string.Empty;
			if (presentationKind != InteractionAnimationPresentationKind.BodyWorld)
			{
				return true;
			}
			Animator val = (((Object)(object)player != (Object)null) ? player.playerBodyAnimator : null);
			if ((Object)(object)val == (Object)null)
			{
				reason = "missing_body_animator";
				return false;
			}
			for (int i = 0; i < conflicts.Length; i++)
			{
				if (activeSessions.TryGetValue(conflicts[i], out var value) && value.Player == player && value.PresentationKind == InteractionAnimationPresentationKind.BodyWorld && value.HasResourceOwnership)
				{
					return true;
				}
			}
			RuntimeAnimatorController val2 = ResolveExpectedVanillaController(player);
			if ((Object)(object)val2 == (Object)null)
			{
				reason = "expected_player_animator_controller_missing";
				return false;
			}
			if ((Object)(object)val.runtimeAnimatorController != (Object)(object)val2)
			{
				reason = "player_animator_owned_externally";
				return false;
			}
			return true;
		}

		private bool TrySuspendConflicts(InteractionAnimationHandle[] handles, out InteractionAnimationSession[] suspended, out string reason)
		{
			reason = string.Empty;
			List<InteractionAnimationSession> list = new List<InteractionAnimationSession>();
			for (int i = 0; i < handles.Length; i++)
			{
				if (!activeSessions.TryGetValue(handles[i], out var value))
				{
					continue;
				}
				if (!value.TrySuspend(out reason))
				{
					for (int j = 0; j < list.Count; j++)
					{
						InteractionAnimationSession interactionAnimationSession = list[j];
						if (!interactionAnimationSession.TryResume(out var _))
						{
							leases.Release(interactionAnimationSession.Handle);
							activeSessions.Remove(interactionAnimationSession.Handle);
							interactionAnimationSession.TryStopAndRestore(InteractionAnimationStopReason.PresenterFailure);
							NotifyEnded(interactionAnimationSession, InteractionAnimationStopReason.PresenterFailure);
						}
					}
					if (value.IsEnded)
					{
						leases.Release(value.Handle);
						activeSessions.Remove(value.Handle);
						NotifyEnded(value, InteractionAnimationStopReason.PresenterFailure);
					}
					suspended = Array.Empty<InteractionAnimationSession>();
					return false;
				}
				list.Add(value);
			}
			suspended = list.ToArray();
			for (int k = 0; k < suspended.Length; k++)
			{
				leases.Release(suspended[k].Handle);
			}
			return true;
		}

		private void ResumeConflicts(InteractionAnimationSession[] sessions)
		{
			foreach (InteractionAnimationSession interactionAnimationSession in sessions)
			{
				bool isLocal = interactionAnimationSession.Player == ResolveLocalPlayer();
				InteractionAnimationResourceClaim[] claims = BuildClaims(interactionAnimationSession.Player, interactionAnimationSession.PresentationKind, isLocal);
				if (!leases.TryAcquire(interactionAnimationSession.Handle, claims, out var reason) || !interactionAnimationSession.TryResume(out reason))
				{
					leases.Release(interactionAnimationSession.Handle);
					activeSessions.Remove(interactionAnimationSession.Handle);
					interactionAnimationSession.TryStopAndRestore(InteractionAnimationStopReason.PresenterFailure);
					NotifyEnded(interactionAnimationSession, InteractionAnimationStopReason.PresenterFailure);
				}
			}
		}

		private void FinalizeConflicts(InteractionAnimationSession[] sessions)
		{
			foreach (InteractionAnimationSession interactionAnimationSession in sessions)
			{
				activeSessions.Remove(interactionAnimationSession.Handle);
				if (interactionAnimationSession.TryFinalizeSuspended())
				{
					NotifyEnded(interactionAnimationSession, InteractionAnimationStopReason.Interrupted);
				}
			}
		}

		private void NotifyEnded(InteractionAnimationSession session, InteractionAnimationStopReason reason)
		{
			LCInteractionAnimationAPI.NotifyInteractionEnded(session.CreateEndedEvent(reason));
		}

		private static InteractionAnimationResourceClaim[] BuildClaims(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, bool isLocal)
		{
			if (presentationKind != InteractionAnimationPresentationKind.DedicatedLocalViewmodel)
			{
				if (!isLocal)
				{
					return new InteractionAnimationResourceClaim[1]
					{
						new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.BodyAnimator, player)
					};
				}
				return new InteractionAnimationResourceClaim[2]
				{
					new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.BodyAnimator, player),
					new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.LocalCameraAndArms, player)
				};
			}
			return new InteractionAnimationResourceClaim[1]
			{
				new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.LocalCameraAndArms, player)
			};
		}

		private PlayerControllerB ResolveLocalPlayer()
		{
			return localPlayerResolver();
		}

		private static PlayerControllerB ResolveDefaultLocalPlayer()
		{
			try
			{
				return GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController;
			}
			catch
			{
				return null;
			}
		}

		private RuntimeAnimatorController ResolveExpectedVanillaController(PlayerControllerB player)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || player == null)
			{
				return null;
			}
			if (player != ResolveLocalPlayer())
			{
				return instance.otherClientsAnimatorController;
			}
			return instance.localClientAnimatorController;
		}

		private IInteractionPresenter CreatePresenter(InteractionAnimationPresentationKind presentationKind)
		{
			return presenterFactory(presentationKind);
		}

		private static IInteractionPresenter CreateDefaultPresenter(InteractionAnimationPresentationKind presentationKind)
		{
			return presentationKind switch
			{
				InteractionAnimationPresentationKind.DedicatedLocalViewmodel => new LocalViewmodelPresenter(), 
				InteractionAnimationPresentationKind.BodyWorld => new LiveBodyAnimatorPresenter(), 
				_ => null, 
			};
		}
	}
	internal sealed class RegisteredPackSnapshot
	{
		private readonly Dictionary<string, RegisteredInteractionSnapshot> interactions;

		internal string PackId { get; }

		internal string Version { get; }

		internal string AssetRootPath { get; }

		internal int InteractionCount => interactions.Count;

		internal RegisteredPackSnapshot(string packId, string version, string assetRootPath, Dictionary<string, RegisteredInteractionSnapshot> interactions)
		{
			PackId = packId;
			Version = version;
			AssetRootPath = assetRootPath;
			this.interactions = interactions;
		}

		internal bool TryGetInteraction(string interactionId, out RegisteredInteractionSnapshot interaction)
		{
			return interactions.TryGetValue(interactionId, out interaction);
		}
	}
	internal sealed class RegisteredInteractionSnapshot
	{
		internal string InteractionId { get; }

		internal InteractionAnimationPresentationKind PresentationKind { get; }

		internal string ManifestJson { get; }

		internal InteractionAnimationManifest Manifest { get; }

		internal RegisteredInteractionSnapshot(string interactionId, InteractionAnimationPresentationKind presentationKind, string manifestJson, InteractionAnimationManifest manifest)
		{
			InteractionId = interactionId;
			PresentationKind = presentationKind;
			ManifestJson = manifestJson;
			Manifest = manifest;
		}

		internal InteractionAnimationDefinition CreateDefinition()
		{
			return new InteractionAnimationDefinition
			{
				InteractionId = InteractionId,
				PresentationKind = PresentationKind,
				ManifestJson = ManifestJson
			};
		}
	}
	internal static class InteractionAnimationPackValidator
	{
		internal static InteractionAnimationValidationReport Validate(InteractionAnimationPackDefinition pack, out RegisteredPackSnapshot snapshot)
		{
			snapshot = null;
			List<InteractionAnimationValidationIssue> issues = new List<InteractionAnimationValidationIssue>();
			if (pack == null)
			{
				AddError(issues, "pack_null", "$", "Pack definition is required.");
				return new InteractionAnimationValidationReport(issues);
			}
			RequireValue(pack.PackId, "$.PackId", "pack_id_empty", issues);
			RequireValue(pack.Version, "$.Version", "pack_version_empty", issues);
			string normalizedRoot = string.Empty;
			if (!InteractionAnimationAssetPathResolver.TryNormalizeAssetRoot(pack.AssetRootPath, out normalizedRoot, out var reason))
			{
				AddError(issues, ReasonCode(reason), "$.AssetRootPath", "AssetRootPath must name an existing directory and is required for path confinement.");
			}
			Dictionary<string, RegisteredInteractionSnapshot> interactions = new Dictionary<string, RegisteredInteractionSnapshot>(StringComparer.OrdinalIgnoreCase);
			if (pack.Interactions == null || pack.Interactions.Length == 0)
			{
				AddError(issues, "pack_interactions_empty", "$.Interactions", "At least one interaction is required.");
			}
			else
			{
				for (int i = 0; i < pack.Interactions.Length; i++)
				{
					ValidateInteraction(pack.Interactions[i], i, interactions, issues);
				}
			}
			InteractionAnimationValidationReport interactionAnimationValidationReport = new InteractionAnimationValidationReport(issues);
			if (interactionAnimationValidationReport.IsValid)
			{
				snapshot = new RegisteredPackSnapshot(pack.PackId, pack.Version, normalizedRoot, interactions);
			}
			return interactionAnimationValidationReport;
		}

		private static void ValidateInteraction(InteractionAnimationDefinition definition, int index, IDictionary<string, RegisteredInteractionSnapshot> interactions, IList<InteractionAnimationValidationIssue> issues)
		{
			string text = "$.Interactions[" + index + "]";
			if (definition == null)
			{
				AddError(issues, "interaction_null", text, "Interaction is required.");
				return;
			}
			RequireValue(definition.InteractionId, text + ".InteractionId", "interaction_id_empty", issues);
			if (!Enum.IsDefined(typeof(InteractionAnimationPresentationKind), definition.PresentationKind))
			{
				AddError(issues, "presentation_kind_invalid", text + ".PresentationKind", "Only BodyWorld and DedicatedLocalViewmodel are supported.");
			}
			InteractionAnimationManifest manifest;
			InteractionAnimationValidationReport interactionAnimationValidationReport = InteractionAnimationManifestValidator.Validate(definition.ManifestJson, definition.InteractionId, definition.PresentationKind, out manifest);
			for (int i = 0; i < interactionAnimationValidationReport.Issues.Count; i++)
			{
				InteractionAnimationValidationIssue interactionAnimationValidationIssue = interactionAnimationValidationReport.Issues[i];
				issues.Add(new InteractionAnimationValidationIssue(interactionAnimationValidationIssue.Code, text + ".ManifestJson" + interactionAnimationValidationIssue.JsonPath.Substring(1), interactionAnimationValidationIssue.Message, interactionAnimationValidationIssue.Severity));
			}
			if (!string.IsNullOrWhiteSpace(definition.InteractionId))
			{
				if (interactions.ContainsKey(definition.InteractionId))
				{
					AddError(issues, "interaction_id_duplicate", text + ".InteractionId", "Interaction ids must be unique within a pack.");
				}
				else if (interactionAnimationValidationReport.IsValid && manifest != null)
				{
					interactions.Add(definition.InteractionId, new RegisteredInteractionSnapshot(definition.InteractionId, definition.PresentationKind, definition.ManifestJson ?? string.Empty, manifest));
				}
			}
		}

		private static void RequireValue(string value, string path, string code, IList<InteractionAnimationValidationIssue> issues)
		{
			if (string.IsNullOrWhiteSpace(value) || value != value.Trim())
			{
				AddError(issues, code, path, "A trimmed non-empty value is required.");
			}
		}

		private static string ReasonCode(string reason)
		{
			if (string.IsNullOrWhiteSpace(reason))
			{
				return "pack_asset_root_invalid";
			}
			int num = reason.IndexOf(':');
			if (num < 0)
			{
				return reason;
			}
			return reason.Substring(0, num);
		}

		private static void AddError(IList<InteractionAnimationValidationIssue> issues, string code, string path, string message)
		{
			issues.Add(new InteractionAnimationValidationIssue(code, path, message, InteractionAnimationValidationSeverity.Error));
		}
	}
	internal enum InteractionAnimationResourceKind
	{
		BodyAnimator,
		LocalCameraAndArms
	}
	internal readonly struct InteractionAnimationResourceClaim : IEquatable<InteractionAnimationResourceClaim>
	{
		internal InteractionAnimationResourceKind Kind { get; }

		internal object Owner { get; }

		internal InteractionAnimationResourceClaim(InteractionAnimationResourceKind kind, object owner)
		{
			Kind = kind;
			Owner = owner;
		}

		public bool Equals(InteractionAnimationResourceClaim other)
		{
			if (Kind == other.Kind)
			{
				return Owner == other.Owner;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is InteractionAnimationResourceClaim other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((int)Kind * 397) ^ ((Owner != null) ? RuntimeHelpers.GetHashCode(Owner) : 0);
		}
	}
	internal sealed class InteractionAnimationResourceLeaseRegistry
	{
		private readonly Dictionary<InteractionAnimationResourceClaim, InteractionAnimationHandle> owners = new Dictionary<InteractionAnimationResourceClaim, InteractionAnimationHandle>();

		private readonly Dictionary<InteractionAnimationHandle, InteractionAnimationResourceClaim[]> claimsByHandle = new Dictionary<InteractionAnimationHandle, InteractionAnimationResourceClaim[]>();

		internal bool TryPlanAcquisition(InteractionAnimationResourceClaim[] claims, InteractionAnimationConflictPolicy policy, out InteractionAnimationHandle[] conflicts, out string reason)
		{
			reason = string.Empty;
			HashSet<InteractionAnimationHandle> hashSet = new HashSet<InteractionAnimationHandle>();
			claims = claims ?? Array.Empty<InteractionAnimationResourceClaim>();
			for (int i = 0; i < claims.Length; i++)
			{
				if (claims[i].Owner == null)
				{
					conflicts = Array.Empty<InteractionAnimationHandle>();
					reason = "interaction_resource_owner_missing";
					return false;
				}
				if (owners.TryGetValue(claims[i], out var value))
				{
					hashSet.Add(value);
				}
			}
			conflicts = new InteractionAnimationHandle[hashSet.Count];
			hashSet.CopyTo(conflicts);
			if (conflicts.Length != 0 && policy == InteractionAnimationConflictPolicy.RejectIfBusy)
			{
				reason = "interaction_resource_busy";
				return false;
			}
			return true;
		}

		internal bool TryAcquire(InteractionAnimationHandle handle, InteractionAnimationResourceClaim[] claims, out string reason)
		{
			reason = string.Empty;
			if (!handle.IsValid || claimsByHandle.ContainsKey(handle))
			{
				reason = "interaction_lease_handle_invalid";
				return false;
			}
			claims = claims ?? Array.Empty<InteractionAnimationResourceClaim>();
			for (int i = 0; i < claims.Length; i++)
			{
				if (claims[i].Owner == null || owners.ContainsKey(claims[i]))
				{
					reason = "interaction_resource_busy";
					return false;
				}
			}
			InteractionAnimationResourceClaim[] array = new InteractionAnimationResourceClaim[claims.Length];
			Array.Copy(claims, array, claims.Length);
			claimsByHandle.Add(handle, array);
			for (int j = 0; j < array.Length; j++)
			{
				owners.Add(array[j], handle);
			}
			return true;
		}

		internal void Release(InteractionAnimationHandle handle)
		{
			if (!claimsByHandle.TryGetValue(handle, out var value))
			{
				return;
			}
			claimsByHandle.Remove(handle);
			for (int i = 0; i < value.Length; i++)
			{
				if (owners.TryGetValue(value[i], out var value2) && value2 == handle)
				{
					owners.Remove(value[i]);
				}
			}
		}

		internal bool IsOwned(InteractionAnimationResourceKind kind, object owner, out InteractionAnimationHandle handle)
		{
			return owners.TryGetValue(new InteractionAnimationResourceClaim(kind, owner), out handle);
		}

		internal void Clear()
		{
			owners.Clear();
			claimsByHandle.Clear();
		}
	}
	internal sealed class InteractionAnimationSession
	{
		private readonly InteractionAnimationContext context;

		private readonly IInteractionPresenter presenter;

		private readonly StartOfRound owningRound;

		private readonly bool wasPlayerControlled;

		private readonly Func<DateTime> utcNow;

		private readonly Func<InteractionAnimationStopReason?> invalidationResolver;

		private DateTime startedUtc;

		private DateTime exitStopAtUtc = DateTime.MaxValue;

		private bool active;

		private bool suspended;

		private bool ended;

		internal InteractionAnimationHandle Handle => context.Handle;

		internal PlayerControllerB Player => context.Request.Player;

		internal string PackId => context.Request.PackId;

		internal string InteractionId => context.Request.InteractionId;

		internal InteractionAnimationPresentationKind PresentationKind => context.Definition.PresentationKind;

		internal bool IsActive
		{
			get
			{
				if (active)
				{
					return !ended;
				}
				return false;
			}
		}

		internal bool IsSuspended
		{
			get
			{
				if (suspended)
				{
					return !ended;
				}
				return false;
			}
		}

		internal bool IsEnded => ended;

		internal bool HasResourceOwnership
		{
			get
			{
				if (active)
				{
					return presenter.HasResourceOwnership;
				}
				return false;
			}
		}

		internal InteractionAnimationSession(InteractionAnimationContext context, IInteractionPresenter presenter, Func<DateTime> utcNow = null, Func<InteractionAnimationStopReason?> invalidationResolver = null)
		{
			this.context = context;
			this.presenter = presenter;
			this.utcNow = utcNow ?? ((Func<DateTime>)(() => DateTime.UtcNow));
			this.invalidationResolver = invalidationResolver ?? new Func<InteractionAnimationStopReason?>(GetInvalidationReason);
			try
			{
				owningRound = StartOfRound.Instance;
			}
			catch
			{
				owningRound = null;
			}
			try
			{
				wasPlayerControlled = context != null && context.Request?.Player?.isPlayerControlled == true;
			}
			catch
			{
				wasPlayerControlled = false;
			}
		}

		internal bool TryPreflight(out string reason)
		{
			reason = string.Empty;
			try
			{
				if (presenter == null)
				{
					reason = "presenter_missing";
					return false;
				}
				return presenter.TryPreflight(context, out reason);
			}
			catch (Exception ex)
			{
				reason = "presenter_preflight_exception:" + ex.GetType().Name;
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.preflight_failed: " + ex));
				}
				return false;
			}
		}

		internal bool TryStart(out string reason)
		{
			reason = string.Empty;
			try
			{
				if (presenter == null)
				{
					reason = "presenter_missing";
					return false;
				}
				if (!presenter.TryStart(context, out reason))
				{
					TryRestore(InteractionAnimationStopReason.PresenterFailure);
					return false;
				}
				startedUtc = utcNow();
				exitStopAtUtc = DateTime.MaxValue;
				active = true;
				suspended = false;
				return true;
			}
			catch (Exception ex)
			{
				reason = "presenter_start_exception:" + ex.GetType().Name;
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.start_failed: " + ex));
				}
				TryRestore(InteractionAnimationStopReason.PresenterFailure);
				return false;
			}
		}

		internal bool TrySuspend(out string reason)
		{
			reason = string.Empty;
			if (!active || ended)
			{
				return false;
			}
			try
			{
				presenter.Stop(InteractionAnimationStopReason.Interrupted);
				active = false;
				suspended = true;
				return true;
			}
			catch (Exception ex)
			{
				active = false;
				suspended = false;
				TryRestore(InteractionAnimationStopReason.PresenterFailure);
				ended = true;
				reason = "presenter_suspend_exception:" + ex.GetType().Name;
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.suspend_failed: " + ex));
				}
				return false;
			}
		}

		internal bool TryResume(out string reason)
		{
			reason = string.Empty;
			if (!suspended || ended)
			{
				return false;
			}
			DateTime dateTime = startedUtc;
			DateTime dateTime2 = exitStopAtUtc;
			if (!TryPreflight(out reason) || !TryStart(out reason))
			{
				return false;
			}
			startedUtc = dateTime;
			exitStopAtUtc = dateTime2;
			return true;
		}

		internal bool TryFinalizeSuspended()
		{
			if (!suspended || ended)
			{
				return false;
			}
			suspended = false;
			ended = true;
			return true;
		}

		internal bool TryStopAndRestore(InteractionAnimationStopReason reason)
		{
			if (ended)
			{
				return false;
			}
			if (active)
			{
				TryRestore(reason);
			}
			active = false;
			suspended = false;
			ended = true;
			return true;
		}

		internal InteractionAnimationStopReason? Tick(float deltaTime)
		{
			if (!active || ended)
			{
				return null;
			}
			InteractionAnimationStopReason? result = invalidationResolver();
			if (result.HasValue)
			{
				return result;
			}
			try
			{
				presenter.Tick(deltaTime);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.tick_failed: " + ex));
				}
				return InteractionAnimationStopReason.PresenterFailure;
			}
			if (presenter.RequestedStopReason.HasValue)
			{
				return presenter.RequestedStopReason;
			}
			DateTime dateTime = utcNow();
			if (dateTime >= exitStopAtUtc)
			{
				return InteractionAnimationStopReason.NaturalEnd;
			}
			float durationSeconds = context.Manifest.durationSeconds;
			if (durationSeconds > 0f && (dateTime - startedUtc).TotalSeconds >= (double)durationSeconds)
			{
				return InteractionAnimationStopReason.NaturalEnd;
			}
			return null;
		}

		internal float BeginExit()
		{
			if (!active || presenter == null)
			{
				return 0f;
			}
			float num = Math.Max(0f, presenter.BeginExit());
			exitStopAtUtc = utcNow().AddSeconds(num);
			return num;
		}

		internal bool TrySetAnimatorParameter(string parameterName, AnimatorControllerParameterType parameterType, float value)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (active && presenter != null)
			{
				return presenter.TrySetAnimatorParameter(parameterName, parameterType, value);
			}
			return false;
		}

		internal InteractionAnimationEndedEventArgs CreateEndedEvent(InteractionAnimationStopReason reason)
		{
			return new InteractionAnimationEndedEventArgs(Handle, Player, PackId, InteractionId, PresentationKind, reason);
		}

		private InteractionAnimationStopReason? GetInvalidationReason()
		{
			//IL_0024: 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)
			PlayerControllerB player = Player;
			try
			{
				if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null)
				{
					goto IL_0033;
				}
				Scene scene = ((Component)player).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					goto IL_0033;
				}
				if (player.isPlayerDead)
				{
					return InteractionAnimationStopReason.PlayerDied;
				}
				if (wasPlayerControlled && !player.isPlayerControlled)
				{
					return InteractionAnimationStopReason.PlayerInvalidated;
				}
				if ((Object)(object)owningRound != (Object)null && (Object)(object)StartOfRound.Instance != (Object)(object)owningRound)
				{
					return InteractionAnimationStopReason.RoundUnloaded;
				}
				goto end_IL_0007;
				IL_0033:
				return InteractionAnimationStopReason.PlayerInvalidated;
				end_IL_0007:;
			}
			catch
			{
				return InteractionAnimationStopReason.PlayerInvalidated;
			}
			return null;
		}

		private void TryRestore(InteractionAnimationStopReason reason)
		{
			try
			{
				presenter?.Stop(reason);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.restore_failed: " + ex));
				}
			}
		}
	}
	public enum InteractionAnimationPresentationKind
	{
		DedicatedLocalViewmodel,
		BodyWorld
	}
	public enum InteractionAnimationConflictPolicy
	{
		RejectIfBusy,
		InterruptExisting
	}
	public enum InteractionAnimationStopReason
	{
		Requested,
		NaturalEnd,
		Interrupted,
		PlayerInvalidated,
		PlayerDied,
		RoundUnloaded,
		PresenterFailure,
		Shutdown
	}
	public readonly struct InteractionAnimationHandle : IEquatable<InteractionAnimationHandle>
	{
		private readonly Guid value;

		public static InteractionAnimationHandle Empty => new InteractionAnimationHandle(Guid.Empty);

		public bool IsValid => value != Guid.Empty;

		private InteractionAnimationHandle(Guid value)
		{
			this.value = value;
		}

		internal static InteractionAnimationHandle NewHandle()
		{
			return new InteractionAnimationHandle(Guid.NewGuid());
		}

		public bool Equals(InteractionAnimationHandle other)
		{
			Guid guid = value;
			return guid.Equals(other.value);
		}

		public override bool Equals(object obj)
		{
			if (obj is InteractionAnimationHandle other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return value.GetHashCode();
		}

		public override string ToString()
		{
			return value.ToString();
		}

		public static bool operator ==(InteractionAnimationHandle left, InteractionAnimationHandle right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(InteractionAnimationHandle left, InteractionAnimationHandle right)
		{
			return !left.Equals(right);
		}
	}
	public sealed class InteractionAnimationPackDefinition
	{
		public string PackId { get; set; } = string.Empty;

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

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

		public InteractionAnimationDefinition[] Interactions { get; set; } = Array.Empty<InteractionAnimationDefinition>();
	}
	public sealed class InteractionAnimationDefinition
	{
		public string InteractionId { get; set; } = string.Empty;

		public InteractionAnimationPresentationKind PresentationKind { get; set; }

		public string ManifestJson { get; set; } = string.Empty;
	}
	public sealed class InteractionAnimationRequest
	{
		public PlayerControllerB Player { get; set; }

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

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

		public InteractionAnimationConflictPolicy ConflictPolicy { get; set; }
	}
	public enum InteractionAnimationValidationSeverity
	{
		Warning,
		Error
	}
	public sealed class InteractionAnimationValidationIssue
	{
		public string Code { get; }

		public string JsonPath { get; }

		public string Message { get; }

		public InteractionAnimationValidationSeverity Severity { get; }

		internal InteractionAnimationValidationIssue(string code, string jsonPath, string message, InteractionAnimationValidationSeverity severity)
		{
			Code = code ?? string.Empty;
			JsonPath = jsonPath ?? "$";
			Message = message ?? string.Empty;
			Severity = severity;
		}
	}
	public sealed class InteractionAnimationValidationReport
	{
		private readonly ReadOnlyCollection<InteractionAnimationValidationIssue> issues;

		public bool IsValid
		{
			get
			{
				for (int i = 0; i < issues.Count; i++)
				{
					if (issues[i].Severity == InteractionAnimationValidationSeverity.Error)
					{
						return false;
					}
				}
				return true;
			}
		}

		public IReadOnlyList<InteractionAnimationValidationIssue> Issues => issues;

		internal InteractionAnimationValidationReport(IList<InteractionAnimationValidationIssue> issues)
		{
			this.issues = new ReadOnlyCollection<InteractionAnimationValidationIssue>(new List<InteractionAnimationValidationIssue>(issues ?? Array.Empty<InteractionAnimationValidationIssue>()));
		}
	}
	public sealed class InteractionAnimationEndedEventArgs : EventArgs
	{
		public InteractionAnimationHandle Handle { get; }

		public PlayerControllerB Player { get; }

		public string PackId { get; }

		public string InteractionId { get; }

		public InteractionAnimationPresentationKind PresentationKind { get; }

		public InteractionAnimationStopReason StopReason { get; }

		internal InteractionAnimationEndedEventArgs(InteractionAnimationHandle handle, PlayerControllerB player, string packId, string interactionId, InteractionAnimationPresentationKind presentationKind, InteractionAnimationStopReason stopReason)
		{
			Handle = handle;
			Player = player;
			PackId = packId ?? string.Empty;
			InteractionId = interactionId ?? string.Empty;
			PresentationKind = presentationKind;
			StopReason = stopReason;
		}
	}
	internal sealed class InteractionAnimationContext
	{
		internal InteractionAnimationHandle Handle { get; }

		internal InteractionAnimationRequest Request { get; }

		internal InteractionAnimationDefinition Definition { get; }

		internal InteractionAnimationManifest Manifest { get; }

		internal string AssetRootPath { get; }

		internal ManualLogSource Logger { get; }

		internal InteractionAnimationContext(InteractionAnimationHandle handle, InteractionAnimationRequest request, InteractionAnimationDefinition definition, InteractionAnimationManifest manifest, string assetRootPath, ManualLogSource logger)
		{
			Handle = handle;
			Request = request;
			Definition = definition;
			Manifest = manifest;
			AssetRootPath = assetRootPath ?? string.Empty;
			Logger = logger;
		}
	}
	public static class LCInteractionAnimationAPI
	{
		private static InteractionAnimationCoordinator coordinator;

		public static bool IsInitialized => coordinator != null;

		public static event EventHandler<InteractionAnimationEndedEventArgs> InteractionEnded;

		public static InteractionAnimationValidationReport ValidateInteractionPack(InteractionAnimationPackDefinition pack)
		{
			RegisteredPackSnapshot snapshot;
			return InteractionAnimationPackValidator.Validate(pack, out snapshot);
		}

		public static InteractionAnimationValidationReport ValidateInteractionManifest(string manifestJson, string expectedInteractionId, InteractionAnimationPresentationKind presentationKind)
		{
			InteractionAnimationManifest manifest;
			return InteractionAnimationManifestValidator.Validate(manifestJson, expectedInteractionId, presentationKind, out manifest);
		}

		public static bool TryRegisterInteractionPack(InteractionAnimationPackDefinition pack, out string reason)
		{
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryRegisterInteractionPack(pack, out reason);
		}

		public static bool TryStartInteraction(InteractionAnimationRequest request, out InteractionAnimationHandle handle, out string reason)
		{
			handle = InteractionAnimationHandle.Empty;
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryStartInteraction(request, out handle, out reason);
		}

		public static bool TryPreloadInteractionAssets(string packId, string interactionId, out string reason)
		{
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryPreloadInteractionAssets(packId, interactionId, out reason);
		}

		public static bool TryStopInteraction(InteractionAnimationHandle handle, InteractionAnimationStopReason stopReason)
		{
			if (coordinator != null)
			{
				return coordinator.TryStopInteraction(handle, stopReason);
			}
			return false;
		}

		public static bool IsInteractionActive(InteractionAnimationHandle handle)
		{
			if (coordinator != null)
			{
				return coordinator.IsInteractionActive(handle);
			}
			return false;
		}

		public static bool TryGetActiveInteraction(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, out InteractionAnimationHandle handle)
		{
			handle = InteractionAnimationHandle.Empty;
			if (coordinator != null)
			{
				return coordinator.TryGetActiveInteraction(player, presentationKind, out handle);
			}
			return false;
		}

		public static bool TrySetInteractionBool(InteractionAnimationHandle handle, string parameterName, bool value)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)4, value ? 1f : 0f);
			}
			return false;
		}

		public static bool TrySetInteractionInt(InteractionAnimationHandle handle, string parameterName, int value)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)3, value);
			}
			return false;
		}

		public static bool TrySetInteractionFloat(InteractionAnimationHandle handle, string parameterName, float value)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)1, value);
			}
			return false;
		}

		public static bool TryFireInteractionTrigger(InteractionAnimationHandle handle, string parameterName)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)9, 0f);
			}
			return false;
		}

		public static bool TryBeginInteractionExit(InteractionAnimationHandle handle, out string reason)
		{
			reason = string.Empty;
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryBeginInteractionExit(handle, out reason);
		}

		internal static void Initialize(InteractionAnimationCoordinator value)
		{
			coordinator = value;
		}

		internal static void NotifyInteractionEnded(InteractionAnimationEndedEventArgs args)
		{
			Delegate[] array = LCInteractionAnimationAPI.InteractionEnded?.GetInvocationList();
			if (array == null)
			{
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				try
				{
					((EventHandler<InteractionAnimationEndedEventArgs>)array[i])(null, args);
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[LCInteractionAnimationAPI] interaction_ended_handler_failed: " + ex));
					}
				}
			}
		}

		internal static void Shutdown()
		{
			coordinator = null;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "UpdatePlayerAnimationsToOtherClients")]
	internal static class PlayerAnimationSyncStateGuardPatch
	{
		[HarmonyPrefix]
		private static void EnsureAnimationStateHashCounts(PlayerControllerB __instance, ref List<int> ___currentAnimationStateHash, ref List<int> ___previousAnimationStateHash)
		{
			int? obj;
			if (__instance == null)
			{
				obj = null;
			}
			else
			{
				Animator playerBodyAnimator = __instance.playerBodyAnimator;
				obj = ((playerBodyAnimator != null) ? new int?(playerBodyAnimator.layerCount) : ((int?)null));
			}
			int? num = obj;
			int valueOrDefault = num.GetValueOrDefault();
			bool num2 = EnsureCount(ref ___currentAnimationStateHash, valueOrDefault);
			bool flag = EnsureCount(ref ___previousAnimationStateHash, valueOrDefault);
			if (num2 || flag)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[LCInteractionAnimationAPI] live_body.sync_state_capacity_expanded: " + $"player={__instance.playerClientId}, layers={valueOrDefault}."));
				}
			}
		}

		internal static bool EnsureCount(ref List<int> states, int requiredCount)
		{
			if (requiredCount > 0)
			{
				List<int> obj = states;
				if (obj == null || obj.Count < requiredCount)
				{
					if (states == null)
					{
						states = new List<int>(requiredCount);
					}
					while (states.Count < requiredCount)
					{
						states.Add(0);
					}
					return true;
				}
			}
			return false;
		}
	}
	internal static class InteractionAnimationApiRestoreDiagnostics
	{
		internal sealed class CameraChainPoseSnapshot
		{
			private readonly Transform[] transforms;

			private readonly Vector3[] localPositions;

			private readonly string[] names;

			internal int Count => transforms.Length;

			internal string MissingTargets { get; }

			internal string Source { get; private set; } = "player_awake_prefix_authored_default";

			private CameraChainPoseSnapshot(Transform[] transforms, Vector3[] localPositions, string[] names, string missingTargets)
			{
				this.transforms = transforms;
				this.localPositions = localPositions;
				this.names = names;
				MissingTargets = missingTargets;
			}

			internal bool RefinePositions(string newSource)
			{
				//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)
				bool flag = false;
				for (int i = 0; i < transforms.Length; i++)
				{
					Transform val = transforms[i];
					if (!((Object)(object)val == (Object)null))
					{
						localPositions[i] = val.localPosition;
						flag = true;
					}
				}
				if (flag)
				{
					Source = newSource;
				}
				return flag;
			}

			internal static CameraChainPoseSnapshot Capture(PlayerControllerB player)
			{
				List<Transform> list = new List<Transform>(4);
				List<Vector3> list2 = new List<Vector3>(4);
				List<string> list3 = new List<string>(4);
				List<string> list4 = new List<string>(4);
				CaptureTarget("cameraContainer", SafeGet(() => player.cameraContainerTransform), list, list2, list3, list4);
				CaptureTarget("gameplayCamera", SafeGet(() => (!((Object)(object)player.gameplayCamera != (Object)null)) ? null : ((Component)player.gameplayCamera).transform), list, list2, list3, list4);
				CaptureTarget("playerModelArmsMetarig", SafeGet(() => player.playerModelArmsMetarig), list, list2, list3, list4);
				CaptureTarget("localArmsTransform", SafeGet(() => player.localArmsTransform), list, list2, list3, list4);
				return new CameraChainPoseSnapshot(list.ToArray(), list2.ToArray(), list3.ToArray(), string.Join(",", list4.ToArray()));
			}

			private static Transform SafeGet(Func<Transform> getter)
			{
				try
				{
					return getter();
				}
				catch
				{
					return null;
				}
			}

			private static void CaptureTarget(string name, Transform target, List<Transform> capturedTransforms, List<Vector3> capturedPositions, List<string> capturedNames, List<string> missing)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)target == (Object)null)
				{
					missing.Add(name);
					return;
				}
				capturedTransforms.Add(target);
				capturedPositions.Add(target.localPosition);
				capturedNames.Add(name);
			}

			internal int RestorePositions()
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				int num = 0;
				for (int i = 0; i < transforms.Length; i++)
				{
					Transform val = transforms[i];
					if (!((Object)(object)val == (Object)null))
					{
						val.localPosition = localPositions[i];
						num++;
					}
				}
				return num;
			}

			internal string DescribePositions()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				List<string> list = new List<string>(names.Length);
				for (int i = 0; i < names.Length; i++)
				{
					list.Add(names[i] + "Local=" + FormatVector(localPositions[i]));
				}
				return string.Join(" ", list.ToArray());
			}
		}

		private sealed class RestoreFrameSample
		{
			internal readonly int[] LayerStateHashes;

			internal readonly float[] LayerNormalizedTimes;

			internal bool Valid;

			internal int Frame;

			internal Vector3 GameplayCameraWorldPosition;

			internal Vector3 CameraContainerLocalPosition;

			internal Vector3 CameraContainerWorldPosition;

			internal Vector3 ArmsMetarigWorldPosition;

			internal string ControllerName;

			internal int ActualLayerCount;

			internal int CapturedLayerCount;

			internal RestoreFrameSample(int maxAnimatorLayers)
			{
				LayerStateHashes = new int[maxAnimatorLayers];
				LayerNormalizedTimes = new float[maxAnimatorLayers];
				ControllerName = "<null>";
			}
		}

		private sealed class RenderSeamFrameSample
		{
			internal bool Valid;

			internal PlayerControllerB Player;

			internal int Frame;

			internal float DeltaTime;

			internal float UnscaledDeltaTime;

			internal RenderPoseSample GameplayCamera;

			internal RenderPoseSample RightHand;

			internal RenderPoseSample LeftHand;

			internal RenderPoseSample ArmsMetarig;

			internal RenderPoseSample LocalArms;

			internal RenderPoseSample LocalVisor;

			internal RenderPoseSample LocalVisorTargetPoint;

			internal RenderVisibilitySample LocalVisorVisibility;

			internal bool VisorCameraPresent;

			internal bool VisorCameraEnabled;

			internal bool CameraParametersPresent;

			internal float CameraFieldOfView;

			internal float CameraNearClipPlane;

			internal RenderVisibilitySample HeldItem;

			internal void CopyFrom(RenderSeamFrameSample other)
			{
				if (other == null)
				{
					Reset();
					return;
				}
				Valid = other.Valid;
				Player = other.Player;
				Frame = other.Frame;
				DeltaTime = other.DeltaTime;
				UnscaledDeltaTime = other.UnscaledDeltaTime;
				GameplayCamera = other.GameplayCamera;
				RightHand = other.RightHand;
				LeftHand = other.LeftHand;
				ArmsMetarig = other.ArmsMetarig;
				LocalArms = other.LocalArms;
				LocalVisor = other.LocalVisor;
				LocalVisorTargetPoint = other.LocalVisorTargetPoint;
				LocalVisorVisibility = other.LocalVisorVisibility;
				VisorCameraPresent = other.VisorCameraPresent;
				VisorCameraEnabled = other.VisorCameraEnabled;
				CameraParametersPresent = other.CameraParametersPresent;
				CameraFieldOfView = other.CameraFieldOfView;
				CameraNearClipPlane = other.CameraNearClipPlane;
				HeldItem = other.HeldItem;
			}

			internal void Reset()
			{
				Valid = false;
				Player = null;
				Frame = 0;
				DeltaTime = 0f;
				UnscaledDeltaTime = 0f;
				GameplayCamera = default(RenderPoseSample);
				RightHand = default(RenderPoseSample);
				LeftHand = default(RenderPoseSample);
				ArmsMetarig = default(RenderPoseSample);
				LocalArms = default(RenderPoseSample);
				LocalVisor = default(RenderPoseSample);
				LocalVisorTargetPoint = default(RenderPoseSample);
				LocalVisorVisibility = default(RenderVisibilitySample);
				VisorCameraPresent = false;
				VisorCameraEnabled = false;
				CameraParametersPresent = false;
				CameraFieldOfView = 0f;
				CameraNearClipPlane = 0f;
				HeldItem = default(RenderVisibilitySample);
			}
		}

		private sealed class RenderSeamWindow
		{
			internal readonly string Phase;

			internal bool Active;

			internal int SeamFrame;

			internal int EndFrame;

			internal int LastLoggedFrame;

			internal GameObject AnimatedProp;

			internal RenderSeamWindow(string phase)
			{
				Phase = phase;
				Reset();
			}

			internal void Activate(int seamFrame, int endFrame, GameObject animatedProp)
			{
				Active = true;
				SeamFrame = seamFrame;
				EndFrame = endFrame;
				LastLoggedFrame = -1;
				AnimatedProp = animatedProp;
			}

			internal void Reset()
			{
				Active = false;
				SeamFrame = 0;
				EndFrame = 0;
				LastLoggedFrame = -1;
				AnimatedProp = null;
			}
		}

		private struct RenderPoseSample
		{
			internal bool Present;

			internal Vector3 WorldPosition;

			internal Vector3 WorldEulerAngles;
		}

		private struct RenderVisibilitySample
		{
			internal bool Present;

			internal string Name;

			internal bool ActiveInHierarchy;

			internal int RendererCount;

			internal int EnabledRendererCount;

			internal bool AnyRendererEnabled;

			internal bool ReadFailed;
		}

		internal sealed class ThirdPersonRigPoseSnapshot
		{
			private readonly ThirdPersonRigPoseBaseline[] baselines;

			internal int FullPoseCount { get; }

			internal int RotationOnlyCount { get; }

			internal int TotalCount => baselines.Length;

			internal bool IsComplete { get; }

			internal string MissingTargets { get; }

			internal bool PlausibleAtCapture { get; private set; }

			internal string Source { get; private set; } = "player_awake_prefix_authored_default";

			internal void SetCaptureMetadata(bool plausibleAtCapture, string source)
			{
				PlausibleAtCapture = plausibleAtCapture;
				Source = source;
			}

			private ThirdPersonRigPoseSnapshot(ThirdPersonRigPoseBaseline[] baselines, int fullPoseCount, int rotationOnlyCount, string[] missingTargets)
			{
				this.baselines = baselines ?? Array.Empty<ThirdPersonRigPoseBaseline>();
				FullPoseCount = fullPoseCount;
				RotationOnlyCount = rotationOnlyCount;
				IsComplete = missingTargets == null || missingTargets.Length == 0;
				MissingTargets = (IsComplete ? "<none>" : string.Join(",", missingTargets));
			}

			internal static ThirdPersonRigPoseSnapshot Capture(PlayerControllerB player)
			{
				Transform val = null;
				try
				{
					val = (((Object)(object)player != (Object)null && (Object)(object)player.playerBodyAnimator != (Object)null) ? ((Component)player.playerBodyAnimator).transform : null);
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Transform parent = FindChildRecursive(val, "spine.003");
				Transform parent2 = FindChildRecursive(val, "Rig 1");
				Transform val2 = FindDirectChild(parent2, "LeftLeg");
				Transform val3 = FindDirectChild(parent2, "RightLeg");
				List<ThirdPersonRigPoseBaseline> list = new List<ThirdPersonRigPoseBaseline>(12);
				HashSet<Transform> capturedTransforms = new HashSet<Transform>();
				List<string> list2 = new List<string>(10);
				AddFullPose(FindDirectChild(parent, "LeftArm_target"), "spine.003/LeftArm_target", list, capturedTransforms, list2);
				AddFullPose(FindDirectChild(parent, "RightArm_target"), "spine.003/RightArm_target", list, capturedTransforms, list2);
				AddControlGroup(val2, "Rig 1/LeftLeg", new string[2] { "LeftLeg_hint", "LeftLeg_target" }, list, capturedTransforms, list2);
				AddControlGroup(val3, "Rig 1/RightLeg", new string[2] { "RightLeg_hint", "RightLeg_target" }, list, capturedTransforms, list2);
				AddRotationOnly(FindChildRecursive(val, "shin.L"), "spine/thigh.L/shin.L", list, capturedTransforms, list2);
				AddRotationOnly(FindChildRecursive(val, "shin.R"), "spine/thigh.R/shin.R", list, capturedTransforms, list2);
				int num = 0;
				int num2 = 0;
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i].RotationOnly)
					{
						num2++;
					}
					else
					{
						num++;
					}
				}
				return new ThirdPersonRigPoseSnapshot(list.ToArray(), num, num2, list2.ToArray());
			}

			private static void AddControlGroup(Transform group, string groupPath, string[] requiredChildren, ICollection<ThirdPersonRigPoseBaseline> captured, ISet<Transform> capturedTransforms, ICollection<string> missing)
			{
				if ((Object)(object)group == (Object)null)
				{
					missing.Add(groupPath);
					for (int i = 0; i < requiredChildren.Length; i++)
					{
						missing.Add(groupPath + "/" + requiredChildren[i]);
					}
					return;
				}
				Transform[] componentsInChildren = ((Component)group).GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					string relativePath = GetRelativePath(group, val);
					string path = ((group == val) ? groupPath : (groupPath + relativePath.Substring(((Object)group).name.Length)));
					AddFullPose(val, path, captured, capturedTransforms, null);
				}
				foreach (string text in requiredChildren)
				{
					if ((Object)(object)FindDirectChild(group, text) == (Object)null)
					{
						missing.Add(groupPath + "/" + text);
					}
				}
			}

			private static void AddFullPose(Transform transform, string path, ICollection<ThirdPersonRigPoseBaseline> captured, ISet<Transform> capturedTransforms, ICollection<string> missing)
			{
				if ((Object)(object)transform == (Object)null)
				{
					missing?.Add(path);
				}
				else if (capturedTransforms.Add(transform))
				{
					captured.Add(new ThirdPersonRigPoseBaseline(transform, path, rotationOnly: false));
				}
			}

			private static void AddRotationOnly(Transform transform, string path, ICollection<ThirdPersonRigPoseBaseline> captured, ISet<Transform> capturedTransforms, ICollection<string> missing)
			{
				if ((Object)(object)transform == (Object)null)
				{
					missing.Add(path);
				}
				else if (capturedTransforms.Add(transform))
				{
					captured.Add(new ThirdPersonRigPoseBaseline(transform, path, rotationOnly: true));
				}
			}

			internal ThirdPersonRigPlausibility EvaluateVanillaRestPlausibility()
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: 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_009a: 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)
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				float num4 = 0f;
				float num5 = 0f;
				float num6 = 0f;
				bool flag = false;
				for (int i = 0; i < baselines.Length; i++)
				{
					ThirdPersonRigPoseBaseline thirdPersonRigPoseBaseline = baselines[i];
					if (!thirdPersonRigPoseBaseline.HasExpectedVanillaRest)
					{
						continue;
					}
					if (!thirdPersonRigPoseBaseline.Finite)
					{
						flag = true;
						continue;
					}
					float num7 = Quaternion.Angle(thirdPersonRigPoseBaseline.ExpectedLocalRotation, thirdPersonRigPoseBaseline.LocalRotation);
					num5 = Mathf.Max(num5, num7);
					if (num7 > 8f)
					{
						num2++;
					}
					if (!thirdPersonRigPoseBaseline.RotationOnly)
					{
						float num8 = Vector3.Distance(thirdPersonRigPoseBaseline.ExpectedLocalPosition, thirdPersonRigPoseBaseline.LocalPosition);
						float num9 = Vector3.Distance(thirdPersonRigPoseBaseline.ExpectedLocalScale, thirdPersonRigPoseBaseline.LocalScale);
						num4 = Mathf.Max(num4, num8);
						num6 = Mathf.Max(num6, num9);
						if (num8 > 0.05f)
						{
							num++;
						}
						if (num9 > 0.01f)
						{
							num3++;
						}
					}
				}
				bool flag2 = IsComplete && !flag && num == 0 && num2 == 0 && num3 == 0;
				string reason = ((!IsComplete) ? "required_transforms_missing" : (flag ? "non_finite_local_pose" : (flag2 ? "within_vanilla_rest_thresholds" : "outside_vanilla_rest_thresholds")));
				return new ThirdPersonRigPlausibility(flag2, reason, num, num2, num3, num4, num5, num6);
			}

			internal void RestoreExcept(ISet<Transform> excludedTransforms, ISet<Transform> restoredTransforms, out int fullPoseRestored, out int rotationOnlyRestored)
			{
				fullPoseRestored = 0;
				rotationOnlyRestored = 0;
				for (int i = 0; i < baselines.Length; i++)
				{
					ThirdPersonRigPoseBaseline thirdPersonRigPoseBaseline = baselines[i];
					Transform transform = thirdPersonRigPoseBaseline.Transform;
					if (!((Object)(object)transform == (Object)null) && (excludedTransforms == null || !excludedTransforms.Contains(transform)) && thirdPersonRigPoseBaseline.Restore())
					{
						restoredTransforms?.Add(transform);
						if (thirdPersonRigPoseBaseline.RotationOnly)
						{
							rotationOnlyRestored++;
						}
						else
						{
							fullPoseRestored++;
						}
					}
				}
			}
		}

		private sealed class ThirdPersonRigPoseBaseline
		{
			internal Transform Transform { get; }

			internal string Path { get; }

			internal bool RotationOnly { get; }

			internal Vector3 LocalPosition { get; }

			internal Quaternion LocalRotation { get; }

			internal Vector3 LocalScale { get; }

			internal bool HasExpectedVanillaRest { get; }

			internal Vector3 ExpectedLocalPosition { get; }

			internal Quaternion ExpectedLocalRotation { get; }

			internal Vector3 ExpectedLocalScale { get; }

			internal bool Finite
			{
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					if (IsFinite(LocalPosition) && IsFinite(LocalRotation))
					{
						return IsFinite(LocalScale);
					}
					return false;
				}
			}

			internal ThirdPersonRigPoseBaseline(Transform transform, string path, bool rotationOnly)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_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_0059: 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_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				Transform = transform;
				Path = path;
				RotationOnly = rotationOnly;
				LocalPosition = transform.localPosition;
				LocalRotation = transform.localRotation;
				LocalScale = transform.localScale;
				HasExpectedVanillaRest = TryGetExpectedVanillaRest(path, out var localPosition, out var localRotation, out var localScale);
				ExpectedLocalPosition = localPosition;
				ExpectedLocalRotation = localRotation;
				ExpectedLocalScale = localScale;
			}

			internal bool Restore()
			{
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: 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)
				if ((Object)(object)Transform == (Object)null)
				{
					return false;
				}
				if (!RotationOnly)
				{
					Transform.localPosition = LocalPosition;
					Transform.localScale = LocalScale;
				}
				Transform.localRotation = LocalRotation;
				return true;
			}

			private static bool TryGetExpectedVanillaRest(string path, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: 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_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_020b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0210: Unknown result type (might be due to invalid IL or missing references)
				//IL_0195: Unknown result type (might be due to invalid IL or missing references)
				//IL_019a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0227: Unknown result type (might be due to invalid IL or missing references)
				//IL_022c: Unknown result type (might be due to invalid IL or missing references)
				//IL_029a: Unknown result type (might be due to invalid IL or missing references)
				//IL_029f: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_02be: Unknown result type (might be due to invalid IL or missing references)
				//IL_02da: Unknown result type (might be due to invalid IL or missing references)
				//IL_02df: Unknown result type (might be due to invalid IL or missing references)
				//IL_0243: 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_0262: Unknown result type (might be due to invalid IL or missing references)
				//IL_0267: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0300: Unknown result type (might be due to invalid IL or missing references)
				//IL_027e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0283: Unknown result type (might be due to invalid IL or missing references)
				localPosition = Vector3.zero;
				localRotation = Quaternion.identity;
				localScale = Vector3.one;
				switch (path)
				{
				case "spine.003/LeftArm_target":
					localPosition = new Vector3(-1.045884f, -0.057756394f, -0.044099636f);
					localRotation = new Quaternion(-0.78043324f, 0.6235791f, 0.028422598f, 0.03557171f);
					return true;
				case "spine.003/RightArm_target":
					localPosition = new Vector3(1.0641153f, -0.06609607f, -0.030803302f);
					localRotation = new Quaternion(-0.7733263f, -0.6323711f, -0.028823216f, 0.0352481f);
					return true;
				case "Rig 1/LeftLeg":
				case "Rig 1/RightLeg":
					localPosition = new Vector3(-9.584f, 0f, -11.081f);
					return true;
				case "Rig 1/LeftLeg/LeftLeg_hint":
					localPosition = new Vector3(1.001f, 0.746f, 2.4f);
					return true;
				case "Rig 1/LeftLeg/LeftLeg_target":
					localPosition = new Vector3(0.99f, 0.209f, 1.011f);
					localRotation = new Quaternion(0.89385676f, -1.803443E-06f, -1.1043475E-06f, 0.4483527f);
					return true;
				case "Rig 1/RightLeg/RightLeg_hint":
					localPosition = new Vector3(1.486f, 0.658f, 2.823f);
					return true;
				case "Rig 1/RightLeg/RightLeg_target":
					localPosition = new Vector3(1.436f, 0.27f, 1.058f);
					localRotation = new Quaternion(0.89385664f, 3.9951823E-07f, -6.130153E-08f, 0.44835275f);
					return true;
				case "spine/thigh.L/shin.L":
					localRotation = new Quaternion(0.036354546f, -0.0022051183f, -0.008516384f, 0.99930024f);
					return true;
				case "spine/thigh.R/shin.R":
					localRotation = new Quaternion(0.036352716f, 0.002243982f, 0.008508066f, 0.9993003f);
					return true;
				default:
					return false;
				}
			}

			private static bool IsFinite(Vector3 value)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				if (IsFinite(value.x) && IsFinite(value.y))
				{
					return IsFinite(value.z);
				}
				return false;
			}

			private static bool IsFinite(Quaternion value)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				if (IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z))
				{
					return IsFinite(value.w);
				}
				return false;
			}

			private static bool IsFinite(float value)
			{
				if (!float.IsNaN(value))
				{
					return !float.IsInfinity(value);
				}
				return false;
			}
		}

		internal readonly struct ThirdPersonRigPlausibility
		{
			internal bool Plausible { get; }

			internal string Reason { get; }

			internal int PositionOutliers { get; }

			internal int RotationOutliers { get; }

			internal int ScaleOutliers { get; }

			internal float MaxPositionDelta { get; }

			internal float MaxRotationDeltaDegrees { get; }

			internal float MaxScaleDelta { get; }

			internal ThirdPersonRigPlausibility(bool plausible, string reason, int positionOutliers, int rotationOutliers, int scaleOutliers, float maxPositionDelta, float maxRotationDeltaDegrees, float maxScaleDelta)
			{
				Plausible = plausible;
				Reason = reason;
				PositionOutliers = positionOutliers;
				RotationOutliers = rotationOutliers;
				ScaleOutliers = scaleOutliers;
				MaxPositionDelta = maxPositionDelta;
				MaxRotationDeltaDegrees = maxRotationDeltaDegrees;
				MaxScaleDelta = maxScaleDelta;
			}
		}

		private sealed class RemoteRigProbeSchedule
		{
			internal PlayerControllerB Player { get; }

			internal int ProbeId { get; }

			internal int RestoreFrame { get; }

			internal float FiveSecondRealtime { get; }

			internal int LateUpdatesRemaining { get; set; }

			internal bool LateUpdateSampleLogged { get; set; }

			internal bool FiveSecondSampleLogged { get; set; }

			internal RemoteRigProbeSchedule(PlayerControllerB player, int probeId, int restoreFrame, float fiveSecondRealtime)
			{
				Player = player;
				ProbeId = probeId;
				RestoreFrame = restoreFrame;
				FiveSecondRealtime = fiveSecondRealtime;
				LateUpdatesRemaining = 2;
			}
		}

		private sealed class PristineRigSnapshot
		{
			internal readonly PlayerControllerB Player;

			internal readonly TransformBaseline[] Transforms;

			internal readonly TwoBoneIkBaseline[] TwoBoneConstraints;

			internal readonly ChainIkBaseline[] ChainConstraints;

			internal readonly RigWeightBaseline[] Rigs;

			internal readonly RigLayerBaseline[] RigLayers;

			private PristineRigSnapshot(PlayerControllerB player, TransformBaseline[] transforms, TwoBoneIkBaseline[] twoBoneConstraints, ChainIkBaseline[] chainConstraints, RigWeightBaseline[] rigs, RigLayerBaseline[] rigLayers)
			{
				Player = player;
				Transforms = transforms;
				TwoBoneConstraints = twoBoneConstraints;
				ChainConstraints = chainConstraints;
				Rigs = rigs;
				RigLayers = rigLayers;
			}

			internal static PristineRigSnapshot Capture(PlayerControllerB player, Transform metarig, Transform rigArms, Type twoBoneIkConstraintType, Type chainIkConstraintType)
			{
				Transform[] componentsInChildren = ((Component)rigArms).GetComponentsInChildren<Transform>(true);
				TransformBaseline[] array = new TransformBaseline[componentsInChildren.Length + 1];
				array[0] = new TransformBaseline(metarig, ((Object)metarig).name + " (metarig root)");
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Transform transform = componentsInChildren[i];
					array[i + 1] = new TransformBaseline(transform, GetRelativePath(metarig, transform));
				}
				Component[] componentsInChildren2 = ((Component)metarig).GetComponentsInChildren<Component>(true);
				List<TwoBoneIkBaseline> list = new List<TwoBoneIkBaseline>();
				List<ChainIkBaseline> list2 = new List<ChainIkBaseline>();
				List<RigWeightBaseline> list3 = new List<RigWeightBaseline>();
				List<RigLayerBaseline> list4 = new List<RigLayerBaseline>();
				foreach (Component val in componentsInChildren2)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					Type type = ((object)val).GetType();
					string? a = type.FullName ?? type.Name;
					string relativePath = GetRelativePath(metarig, val.transform);
					if (twoBoneIkConstraintType != null && twoBoneIkConstraintType.IsAssignableFrom(type))
					{
						list.Add(new TwoBoneIkBaseline(val, relativePath));
					}
					if (chainIkConstraintType != null && chainIkConstraintType.IsAssignableFrom(type))
					{
						list2.Add(new ChainIkBaseline(val, relativePath));
					}
					if (string.Equals(a, "UnityEngine.Animations.Rigging.Rig", StringComparison.Ordinal))
					{
						list3.Add(new RigWeightBaseline(val, relativePath));
					}
					if (!string.Equals(a, "UnityEngine.Animations.Rigging.RigBuilder", StringComparison.Ordinal) || !(ReadMember(val, "layers", "m_RigLayers") is IList list5))
					{
						continue;
					}
					for (int k = 0; k < list5.Count; k++)
					{
						object obj = list5[k];
						if (obj != null)
						{
							list4.Add(new RigLayerBaseline(obj, relativePath + "/layer[" + k.ToString(CultureInfo.InvariantCulture) + "]"));
						}
					}
				}
				return new PristineRigSnapshot(player, array, list.ToArray(), list2.ToArray(), list3.ToArray(), list4.ToArray());
			}

			internal int RestoreRigControlPose(Transform rigArms, ISet<Transform> restoredTransforms)
			{
				int num = 0;
				for (int i = 0; i < Transforms.Length; i++)
				{
					TransformBaseline transformBaseline = Transforms[i];
					Transform transform = transformBaseline.Transform;
					if (!((Object)(object)transform == (Object)null) && (transform == rigArms || transform.IsChildOf(rigArms)))
					{
						transformBaseline.Restore();
						restoredTransforms.Add(transform);
						num++;
					}
				}
				return num;
			}
		}

		private sealed class TransformBaseline
		{
			internal readonly Transform Transform;

			internal readonly string Path;

			internal readonly Vector3 LocalPosition;

			internal readonly Quaternion LocalRotation;

			internal readonly Vector3 LocalScale;

			internal TransformBaseline(Transform transform, string path)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				Transform = transform;
				Path = path;
				LocalPosition = transform.localPosition;
				LocalRotation = transform.localRotation;
				LocalScale = transform.localScale;
			}

			internal void Restore()
			{
				//IL_0007: 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_0029: Unknown result type (might be due to invalid IL or missing references)
				Transform.localPosition = LocalPosition;
				Transform.localRotation = LocalRotation;
				Transform.localScale = LocalScale;
			}
		}

		private readonly struct TwoBoneIkValues : IEquatable<TwoBoneIkValues>
		{
			internal readonly string TargetName;

			internal readonly string HintName;

			internal readonly float Weight;

			internal readonly float TargetPositionWeight;

			internal readonly float TargetRotationWeight;

			internal readonly float HintWeight;

			internal readonly bool MaintainTargetPositionOffset;

			internal readonly bool MaintainTargetRotationOffset;

			internal TwoBoneIkValues(Component component)
			{
				object instance = ReadMember(component, null, "m_Data");
				TargetName = ReadObjectName(instance, "target", "m_Target");
				HintName = ReadObjectName(instance, "hint", "m_Hint");
				Weight = ReadFloat(component, "weight", "m_Weight");
				TargetPositionWeight = ReadFloat(instance, "targetPositionWeight", "m_TargetPositionWeight");
				TargetRotationWeight = ReadFloat(instance, "targetRotationWeight", "m_TargetRotationWeight");
				HintWeight = ReadFloat(instance, "hintWeight", "m_HintWeight");
				MaintainTargetPositionOffset = ReadBool(instance, "maintainTargetPositionOffset", "m_MaintainTargetPositionOffset");
				MaintainTargetRotationOffset = ReadBool(instance, "maintainTargetRotationOffset", "m_MaintainTargetRotationOffset");
			}

			public bool Equals(TwoBoneIkValues other)
			{
				if (string.Equals(TargetName, other.TargetName, StringComparison.Ordinal) && string.Equals(HintName, other.HintName, StringComparison.Ordinal) && Weight.Equals(other.Weight) && TargetPositionWeight.Equals(other.TargetPositionWeight) && TargetRotationWeight.Equals(other.TargetRotationWeight) && HintWeight.Equals(other.HintWeight) && MaintainTargetPositionOffset == other.MaintainTargetPositionOffset)
				{
					return MaintainTargetRotationOffset == other.MaintainTargetRotationOffset;
				}
				return false;
			}
		}

		private sealed class TwoBoneIkBaseline
		{
			private readonly Component component;

			internal readonly string Path;

			internal readonly TwoBoneIkValues Values;

			internal TwoBoneIkBaseline(Component component, string path)
			{
				this.component = component;
				Path = path;
				Values = new TwoBoneIkValues(component);
			}

			internal bool TryReadCurrent(out TwoBoneIkValues current)
			{
				if ((Object)(object)component == (Object)null)
				{
					current = default(TwoBoneIkValues);
					return false;
				}
				current = new TwoBoneIkValues(component);
				return true;
			}
		}

		private readonly struct ChainIkValues : IEquatable<ChainIkValues>
		{
			internal readonly string RootName;

			internal readonly string TipName;

			internal readonly string TargetName;

			internal readonly float Weight;

			internal readonly float ChainRotationWeight;

			internal readonly float TipRotationWeight;

			internal readonly int MaxIterations;

			internal readonly float Tolerance;

			internal readonly bool MaintainTargetPositionOffset;

			internal readonly bool MaintainTargetRotationOffset;

			internal ChainIkValues(Component component)
			{
				object instance = ReadMember(component, null, "m_Data");
				RootName = ReadObjectName(instance, "root", "m_Root");
				TipName = ReadObjectName(instance, "tip", "m_Tip");
				TargetName = ReadObjectName(instance, "target", "m_Target");
				Weight = ReadFloat(component, "weight", "m_Weight");
				ChainRotationWeight = ReadFloat(instance, "chainRotationWeight", "m_ChainRotationWeight");
				TipRotationWeight = ReadFloat(instance, "tipRotationWeight", "m_TipRotationWeight");
				MaxIterations = ReadInt(instance, "maxIterations", "m_MaxIterations");
				Tolerance = ReadFloat(instance, "tolerance", "m_Tolerance");
				MaintainTargetPositionOffset = ReadBool(instance, "maintainTargetPositionOffset", "m_MaintainTargetPositionOffset");
				MaintainTargetRotationOffset = ReadBool(instance, "maintainTargetRotationOffset", "m_MaintainTargetRotationOffset");
			}

			public bool Equals(ChainIkValues other)
			{
				if (string.Equals(RootName, other.RootName, StringComparison.Ordinal) && string.Equals(TipName, other.TipName, StringComparison.Ordinal) && string.Equals(TargetName, other.TargetName, StringComparison.Ordinal) && Weight.Equals(other.Weight) && ChainRotationWeight.Equals(other.ChainRotationWeight) && TipRotationWeight.Equals(other.TipRotationWeight) && MaxIterations == other.MaxIterations && Tolerance.Equals(other.Tolerance) && MaintainTargetPositionOffset == other.MaintainTargetPositionOffset)
				{
					return MaintainTargetRotationOffset == other.MaintainTargetRotationOffset;
				}
				return false;
			}
		}

		private