Decompiled source of Everything is Multiplayer v0.7.0

BepInEx\plugins\Everything_is_Multiplayer.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using MoreMountains.Tools;
using MoreMountains.TopDownEngine;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using World;
using World.AI;
using World.AI.PreventBeingAttackedOnSight;
using World.Burrows;
using World.Characters;
using World.Characters.Bosses;
using World.Characters.Enemies.Navigation;
using World.CustomTDEAbilities;
using World.Evolutions;
using World.Evolutions.Abilities.Attacks;
using World.Evolutions.Abilities.Dashes;
using World.Evolutions.Specializations;
using World.Evolutions.UI;
using World.HeatAndCold;
using World.Items;
using World.Mushrooms;
using World.Mushrooms.Effects;
using World.Stats;
using World.Stats.StatValueTypes;
using World.TimeManagement;
using World.UI;
using World.UI.HUD;
using World.UI.MainMenuScreen;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Everything_is_Multiplayer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+24fd158a5b1ed61a4eaa20c2f65c0bde0a4af2de")]
[assembly: AssemblyProduct("Everything_is_Multiplayer")]
[assembly: AssemblyTitle("Everything_is_Multiplayer")]
[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 Everything_is_Multiplayer
{
	public sealed class CoopMainMenuController : MonoBehaviour
	{
		private sealed class ButtonLayoutState
		{
			public RectTransform Rect;

			public Vector2 AnchoredPosition;

			public Vector3 LocalScale;

			public Navigation Navigation;
		}

		private const string CoopButtonName = "Everything_is_Multiplayer_CoopButton";

		private const float MenuButtonScale = 0.84f;

		private readonly List<ButtonLayoutState> _originalButtonLayouts = new List<ButtonLayoutState>();

		private MainMenuScreenUI _mainMenu;

		private Button_ODD _coopButton;

		private int _mainMenuId;

		private string _lastWaitReason = string.Empty;

		public static CoopMainMenuController Instance { get; private set; }

		public bool IsCoopButtonVisible
		{
			get
			{
				if ((Object)(object)_coopButton != (Object)null && (Object)(object)((Component)_coopButton).gameObject != (Object)null)
				{
					return ((Component)_coopButton).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		public bool IsUsingStockButton
		{
			get
			{
				if ((Object)(object)_coopButton != (Object)null)
				{
					return (Object)(object)((Il2CppObjectBase)_coopButton).TryCast<Button_ODD>() != (Object)null;
				}
				return false;
			}
		}

		public string SelectedMode => CoopSession.Mode.ToString();

		public CoopMainMenuController(IntPtr ptr)
			: base(ptr)
		{
		}

		public CoopMainMenuController()
			: base(ClassInjector.DerivedConstructorPointer<CoopMainMenuController>())
		{
			ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
		}

		public void Awake()
		{
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Plugin.Logger.LogInfo((object)"Co-op main-menu controller initialized.");
		}

		public void Update()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			CoopSession.ObserveActiveScene();
			if (Plugin.ModEnabled.Value)
			{
				Scene activeScene = SceneManager.GetActiveScene();
				if (string.Equals(((Scene)(ref activeScene)).name, "MainMenu", StringComparison.OrdinalIgnoreCase))
				{
					MainMenuScreenUI val = Object.FindObjectOfType<MainMenuScreenUI>(true);
					if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null)
					{
						LogWaitReason("MainMenuScreenUI is not available yet");
						TeardownMenuButton();
						return;
					}
					if (_mainMenuId != ((Object)val).GetInstanceID())
					{
						TeardownMenuButton();
						_mainMenu = val;
						_mainMenuId = ((Object)val).GetInstanceID();
					}
					EnsureCoopButton();
					RefreshCoopButtonState();
					return;
				}
			}
			TeardownMenuButton();
		}

		public bool InvokeCoopButtonForDebug()
		{
			if (!IsCoopButtonVisible || !((Selectable)_coopButton).interactable)
			{
				return false;
			}
			((UnityEvent)((Button)_coopButton).onClick).Invoke();
			return true;
		}

		public bool VerifyNewRunSelectsSinglePlayerForDebug()
		{
			CoopSession.BeginCoopLaunch();
			CoopSession.EndCoopLaunch();
			CoopSession.SelectSinglePlayerFromNewRun();
			return CoopSession.Mode == LocalRunMode.SinglePlayer;
		}

		public void OnDestroy()
		{
			TeardownMenuButton();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		[HideFromIl2Cpp]
		private void EnsureCoopButton()
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			if ((Object)(object)_coopButton != (Object)null)
			{
				return;
			}
			if ((Object)(object)_mainMenu == (Object)null)
			{
				LogWaitReason("the tracked MainMenuScreenUI is null");
				return;
			}
			if ((Object)(object)_mainMenu._startRunButton == (Object)null)
			{
				LogWaitReason("the stock New Run button field is null");
				return;
			}
			Button_ODD startRunButton = _mainMenu._startRunButton;
			RectTransform component = ((Component)startRunButton).GetComponent<RectTransform>();
			if ((Object)(object)component == (Object)null || (Object)(object)((Transform)component).parent == (Object)null)
			{
				LogWaitReason("the stock New Run button has no parent RectTransform");
				return;
			}
			CaptureOriginalButtonLayouts();
			GameObject val = Object.Instantiate<GameObject>(((Component)startRunButton).gameObject, ((Transform)component).parent, false);
			((Object)val).name = "Everything_is_Multiplayer_CoopButton";
			_coopButton = val.GetComponent<Button_ODD>();
			if ((Object)(object)_coopButton == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				RestoreOriginalButtonLayouts();
				return;
			}
			((UnityEventBase)((Button)_coopButton).onClick).RemoveAllListeners();
			((UnityEvent)((Button)_coopButton).onClick).AddListener(DelegateSupport.ConvertDelegate<UnityAction>((Delegate)new Action(OnCoopPressed)));
			((Selectable)_coopButton).navigation = new Navigation
			{
				mode = (Mode)3
			};
			foreach (ShortcutHint componentsInChild in val.GetComponentsInChildren<ShortcutHint>(true))
			{
				((Component)componentsInChild).gameObject.SetActive(false);
			}
			SetCoopButtonLabel();
			ArrangeMenuButtons();
			_lastWaitReason = string.Empty;
			Plugin.Logger.LogInfo((object)"Added the stock-styled Co-op button to the main menu.");
		}

		private void CaptureOriginalButtonLayouts()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			_originalButtonLayouts.Clear();
			foreach (Button_ODD originalMenuButton in GetOriginalMenuButtons())
			{
				RectTransform val = (((Object)(object)originalMenuButton != (Object)null) ? ((Component)originalMenuButton).GetComponent<RectTransform>() : null);
				if (!((Object)(object)val == (Object)null))
				{
					_originalButtonLayouts.Add(new ButtonLayoutState
					{
						Rect = val,
						AnchoredPosition = val.anchoredPosition,
						LocalScale = ((Transform)val).localScale,
						Navigation = ((Selectable)originalMenuButton).navigation
					});
				}
			}
		}

		private void ArrangeMenuButtons()
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			Button_ODD[] array = (Button_ODD[])(object)new Button_ODD[6] { _mainMenu._startRunButton, _coopButton, _mainMenu._challengesButton, _mainMenu._codexButton, _mainMenu._settingsButton, _mainMenu._quitButton };
			if (_originalButtonLayouts.Count < 2)
			{
				return;
			}
			ButtonLayoutState buttonLayoutState = _originalButtonLayouts[0];
			ButtonLayoutState buttonLayoutState2 = _originalButtonLayouts[_originalButtonLayouts.Count - 1];
			for (int i = 0; i < array.Length; i++)
			{
				Button_ODD val = array[i];
				RectTransform val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<RectTransform>() : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					float num = ((array.Length <= 1) ? 0f : ((float)i / (float)(array.Length - 1)));
					val2.anchoredPosition = Vector2.Lerp(buttonLayoutState.AnchoredPosition, buttonLayoutState2.AnchoredPosition, num);
					((Transform)val2).localScale = new Vector3(buttonLayoutState.LocalScale.x, buttonLayoutState.LocalScale.y * 0.84f, buttonLayoutState.LocalScale.z);
					((Selectable)val).navigation = new Navigation
					{
						mode = (Mode)3
					};
					((Transform)val2).SetSiblingIndex(Mathf.Min(((Transform)buttonLayoutState.Rect).GetSiblingIndex() + i, ((Transform)val2).parent.childCount - 1));
				}
			}
		}

		private void RefreshCoopButtonState()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_coopButton == (Object)null) && !((Object)(object)_mainMenu == (Object)null))
			{
				bool flag = ((Behaviour)_mainMenu).isActiveAndEnabled && !_mainMenu._isWaitingOnInitialInteraction && (int)_mainMenu._currentState == 0 && (Object)(object)_mainMenu._startRunButton != (Object)null && ((Component)_mainMenu._startRunButton).gameObject.activeInHierarchy;
				((Component)_coopButton).gameObject.SetActive(flag);
				((Selectable)_coopButton).interactable = flag && ((Selectable)_mainMenu._startRunButton).interactable;
				SetCoopButtonLabel();
			}
		}

		private void SetCoopButtonLabel()
		{
			if ((Object)(object)_coopButton == (Object)null)
			{
				return;
			}
			foreach (TMP_Text componentsInChild in ((Component)_coopButton).GetComponentsInChildren<TMP_Text>(true))
			{
				componentsInChild.text = "CO-OP";
			}
			foreach (Text componentsInChild2 in ((Component)_coopButton).GetComponentsInChildren<Text>(true))
			{
				componentsInChild2.text = "CO-OP";
			}
		}

		private void OnCoopPressed()
		{
			if ((Object)(object)_mainMenu == (Object)null)
			{
				return;
			}
			CoopSession.BeginCoopLaunch();
			try
			{
				_mainMenu.BTN_NewRunPressed();
			}
			finally
			{
				CoopSession.EndCoopLaunch();
			}
		}

		[HideFromIl2Cpp]
		private IEnumerable<Button_ODD> GetOriginalMenuButtons()
		{
			MainMenuScreenUI mainMenu = _mainMenu;
			yield return (mainMenu != null) ? mainMenu._startRunButton : null;
			MainMenuScreenUI mainMenu2 = _mainMenu;
			yield return (mainMenu2 != null) ? mainMenu2._challengesButton : null;
			MainMenuScreenUI mainMenu3 = _mainMenu;
			yield return (mainMenu3 != null) ? mainMenu3._codexButton : null;
			MainMenuScreenUI mainMenu4 = _mainMenu;
			yield return (mainMenu4 != null) ? mainMenu4._settingsButton : null;
			MainMenuScreenUI mainMenu5 = _mainMenu;
			yield return (mainMenu5 != null) ? mainMenu5._quitButton : null;
		}

		private void TeardownMenuButton()
		{
			if ((Object)(object)_coopButton != (Object)null && (Object)(object)((Component)_coopButton).gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_coopButton).gameObject);
			}
			_coopButton = null;
			RestoreOriginalButtonLayouts();
			_mainMenu = null;
			_mainMenuId = 0;
		}

		private void RestoreOriginalButtonLayouts()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			foreach (ButtonLayoutState originalButtonLayout in _originalButtonLayouts)
			{
				if (!((Object)(object)originalButtonLayout.Rect == (Object)null) && !((Object)(object)((Component)originalButtonLayout.Rect).gameObject == (Object)null))
				{
					originalButtonLayout.Rect.anchoredPosition = originalButtonLayout.AnchoredPosition;
					((Transform)originalButtonLayout.Rect).localScale = originalButtonLayout.LocalScale;
					Button_ODD component = ((Component)originalButtonLayout.Rect).GetComponent<Button_ODD>();
					if ((Object)(object)component != (Object)null)
					{
						((Selectable)component).navigation = originalButtonLayout.Navigation;
					}
				}
			}
			_originalButtonLayouts.Clear();
		}

		private void LogWaitReason(string reason)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (!string.Equals(_lastWaitReason, reason, StringComparison.Ordinal))
			{
				_lastWaitReason = reason;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Waiting to add the Co-op button: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				logger.LogInfo(val);
			}
		}
	}
	internal enum LocalRunMode
	{
		SinglePlayer,
		Coop
	}
	internal static class CoopSession
	{
		private static int _observedMainMenuHandle;

		private static bool _hasObservedMainMenu;

		private static bool _coopLaunchInProgress;

		private static LocalRunMode _mode;

		public static LocalRunMode Mode => _mode;

		public static bool IsCoopActive
		{
			get
			{
				if (Plugin.ModEnabled.Value)
				{
					return _mode == LocalRunMode.Coop;
				}
				return false;
			}
		}

		public static bool IsCoopLaunchInProgress => _coopLaunchInProgress;

		public static void ObserveActiveScene()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (string.Equals(((Scene)(ref activeScene)).name, "MainMenu", StringComparison.OrdinalIgnoreCase) && (!_hasObservedMainMenu || _observedMainMenuHandle != ((Scene)(ref activeScene)).handle))
			{
				_hasObservedMainMenu = true;
				_observedMainMenuHandle = ((Scene)(ref activeScene)).handle;
				SelectSinglePlayer("entered main menu");
			}
		}

		public static void SelectSinglePlayerFromNewRun()
		{
			if (!_coopLaunchInProgress)
			{
				SelectSinglePlayer("New Run selected");
			}
		}

		public static void BeginCoopLaunch()
		{
			_mode = LocalRunMode.Coop;
			_coopLaunchInProgress = true;
			Plugin.Logger.LogInfo((object)"Co-op selected from the main menu.");
		}

		public static void EndCoopLaunch()
		{
			_coopLaunchInProgress = false;
		}

		private static void SelectSinglePlayer(string reason)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			bool num = _mode != LocalRunMode.SinglePlayer;
			_mode = LocalRunMode.SinglePlayer;
			_coopLaunchInProgress = false;
			if (num)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Single-player mode selected (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
				}
				logger.LogInfo(val);
			}
		}
	}
	public sealed class LocalMultiplayerDriver : MonoBehaviour
	{
		private sealed class BoundGameplayActions
		{
			public BoundActionReader Move;

			public BoundActionReader Aim;

			public BoundActionReader PrimaryAttack;

			public BoundActionReader SecondaryAttack;

			public BoundActionReader UltimateAttack;

			public BoundActionReader Dash;

			public BoundActionReader Interact;

			public bool IsReady
			{
				get
				{
					BoundActionReader move = Move;
					if (move != null && move.ControlCount > 0)
					{
						BoundActionReader aim = Aim;
						if (aim != null && aim.ControlCount > 0)
						{
							BoundActionReader primaryAttack = PrimaryAttack;
							if (primaryAttack != null && primaryAttack.ControlCount > 0)
							{
								BoundActionReader secondaryAttack = SecondaryAttack;
								if (secondaryAttack != null && secondaryAttack.ControlCount > 0)
								{
									BoundActionReader ultimateAttack = UltimateAttack;
									if (ultimateAttack != null && ultimateAttack.ControlCount > 0)
									{
										BoundActionReader dash = Dash;
										if (dash != null && dash.ControlCount > 0)
										{
											BoundActionReader interact = Interact;
											if (interact == null)
											{
												return false;
											}
											return interact.ControlCount > 0;
										}
									}
								}
							}
						}
					}
					return false;
				}
			}

			public void Dispose()
			{
				Move = null;
				Aim = null;
				PrimaryAttack = null;
				SecondaryAttack = null;
				UltimateAttack = null;
				Dash = null;
				Interact = null;
			}

			public string Describe()
			{
				return $"move={Move?.Describe()}; aim={Aim?.Describe()}; primary={PrimaryAttack?.Describe()}; secondary={SecondaryAttack?.Describe()}; ultimate={UltimateAttack?.Describe()}; dash={Dash?.Describe()}; interact={Interact?.Describe()}";
			}
		}

		private sealed class BoundActionReader
		{
			private readonly List<BoundControl> _controls = new List<BoundControl>();

			public string ActionName { get; private set; } = string.Empty;

			public int ControlCount => _controls.Count;

			public static BoundActionReader Create(InputActionMap map, string actionName, Gamepad gamepad, string fallbackActionName = null)
			{
				BoundActionReader boundActionReader = new BoundActionReader();
				InputAction val = map.FindAction(actionName, false);
				if (val == null && !string.IsNullOrEmpty(fallbackActionName))
				{
					val = map.FindAction(fallbackActionName, false);
				}
				boundActionReader.ActionName = ((val != null) ? val.name : null) ?? actionName;
				if (val == null)
				{
					return boundActionReader;
				}
				ReadOnlyArray<InputBinding> bindings = val.bindings;
				for (int i = 0; i < bindings.Count; i++)
				{
					InputBinding val2 = bindings[i];
					if (!val2.isComposite && !string.IsNullOrWhiteSpace(val2.effectivePath))
					{
						InputControl val3 = ResolveControl(gamepad, val2.effectivePath);
						if (val3 != null)
						{
							boundActionReader._controls.Add(new BoundControl
							{
								Control = val3,
								Part = (val2.isPartOfComposite ? (val2.name ?? string.Empty) : string.Empty),
								Path = val2.effectivePath
							});
						}
					}
				}
				return boundActionReader;
			}

			public Vector2 ReadVector()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				Vector2 val = Vector2.zero;
				foreach (BoundControl control in _controls)
				{
					Vector2Control val2 = ((Il2CppObjectBase)control.Control).TryCast<Vector2Control>();
					if (val2 != null)
					{
						Vector2 val3 = ((InputControl<Vector2>)(object)val2).ReadValue();
						if (((Vector2)(ref val3)).sqrMagnitude > ((Vector2)(ref val)).sqrMagnitude)
						{
							val = val3;
						}
						continue;
					}
					AxisControl val4 = ((Il2CppObjectBase)control.Control).TryCast<AxisControl>();
					if (val4 != null)
					{
						float num = ((InputControl<float>)(object)val4).ReadValue();
						switch (control.Part.ToLowerInvariant())
						{
						case "up":
							val.y += num;
							break;
						case "down":
							val.y -= num;
							break;
						case "left":
							val.x -= num;
							break;
						case "right":
							val.x += num;
							break;
						}
					}
				}
				return Vector2.ClampMagnitude(val, 1f);
			}

			public bool IsPressed()
			{
				foreach (BoundControl control in _controls)
				{
					ButtonControl val = ((Il2CppObjectBase)control.Control).TryCast<ButtonControl>();
					if (val != null && val.isPressed)
					{
						return true;
					}
					AxisControl val2 = ((Il2CppObjectBase)control.Control).TryCast<AxisControl>();
					if (val2 != null && ((InputControl<float>)(object)val2).ReadValue() >= Plugin.TriggerThreshold.Value)
					{
						return true;
					}
				}
				return false;
			}

			public string Describe()
			{
				if (_controls.Count == 0)
				{
					return ActionName + "[unresolved]";
				}
				string[] array = new string[_controls.Count];
				for (int i = 0; i < _controls.Count; i++)
				{
					int num = i;
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(1, 2);
					defaultInterpolatedStringHandler.AppendFormatted(_controls[i].Path);
					defaultInterpolatedStringHandler.AppendLiteral("@");
					InputControl control = _controls[i].Control;
					int? value;
					if (control == null)
					{
						value = null;
					}
					else
					{
						InputDevice device = control.device;
						value = ((device != null) ? new int?(device.deviceId) : ((int?)null));
					}
					defaultInterpolatedStringHandler.AppendFormatted(value);
					array[num] = defaultInterpolatedStringHandler.ToStringAndClear();
				}
				return ActionName + "[" + string.Join("|", array) + "]";
			}

			private static InputControl ResolveControl(Gamepad gamepad, string path)
			{
				int num = path.IndexOf(">/", StringComparison.Ordinal);
				string text = ((num >= 0) ? path.Substring(num + 2) : path.TrimStart('/'));
				InputControl val = InputControlPath.TryFindControl((InputControl)(object)gamepad, text, 0);
				if (((val != null) ? val.device : null) != null && val.device.deviceId == ((InputDevice)gamepad).deviceId)
				{
					return val;
				}
				val = InputControlPath.TryFindControl((InputControl)(object)gamepad, path, 0);
				if (((val != null) ? val.device : null) == null || val.device.deviceId != ((InputDevice)gamepad).deviceId)
				{
					return null;
				}
				return val;
			}
		}

		private sealed class BoundControl
		{
			public InputControl Control;

			public string Part;

			public string Path;
		}

		private sealed class NightVisionMaterialState
		{
			public Material Material;

			public Vector4 BaseCenter;

			public float BaseViewportRadius;

			public float BaseGradientRadius;

			public Vector4 LastAppliedCenter = new Vector4(float.NaN, float.NaN, float.NaN, float.NaN);

			public float LastAppliedViewportRadius = float.NaN;

			public float LastAppliedGradientRadius = float.NaN;
		}

		private const string PlayerTwoName = "LocalMultiplayer_Player2";

		private const string PlayerOnePendingDestroyName = "LocalMultiplayer_Player1_PendingDestroy";

		private const string PlayerOneLabelName = "LocalMultiplayer_Player1_Label";

		private const string PlayerTwoLabelName = "LocalMultiplayer_Player2_Label";

		private static readonly Color PlayerOneLabelColor = new Color(0.56f, 0.95f, 0.65f, 1f);

		private static readonly Color PlayerTwoTint = new Color(0.55f, 0.9f, 1f, 1f);

		private int _sceneHandle;

		private int _playerOneId;

		private int _playerTwoId;

		private int _cameraId;

		private int _lastGamepadCount = -1;

		private float _baseOrthographicSize;

		private float _smoothedOrthographicSize;

		private Vector2 _smoothedCameraCenter;

		private bool _hasSharedCameraState;

		private int _cameraEnforcerId;

		private readonly Dictionary<int, NightVisionMaterialState> _nightVisionMaterialStates = new Dictionary<int, NightVisionMaterialState>();

		private bool _previousDashHeld;

		private bool _previousInteractHeld;

		private bool _loggedPlayerTwoInput;

		private bool _loggedFilteredStockInput;

		private bool _loggedGameplaySpawnFallback;

		private bool _loggedPlayerTwoDamageAttempt;

		private bool _loggedPlayerTwoDamageOutputOverride;

		private bool _loggedPlayerTwoMasterHealthCleared;

		private bool _loggedPlayerTwoColliderState;

		private bool _loggedPlayerTwoPhysicalColliderEnabled;

		private bool _loggedPlayerTwoRigidbodyEnabled;

		private bool _loggedPlayerTwoDamageOnTouchCollision;

		private bool _loggedPlayerTwoDamageOnTouchMaskPatched;

		private bool _loggedPlayerTwoDamageOnTouchIgnoreCleared;

		private bool _loggedPlayerTwoDamageOnTouchFallback;

		private bool _loggedPlayerTwoAiIgnoreCleared;

		private bool _loggedPlayerTwoDirectAiRegistration;

		private bool _loggedPlayerTwoDirectAiRegistrationFailure;

		private bool _loggedPlayerTwoAttackScoreForced;

		private bool _loggedPlayerTwoTargetConsidered;

		private bool _loggedPlayerTwoPreventSightBypass;

		private bool _loggedFriendlyFireSuppressed;

		private int _playerTwoDamageResultLogs;

		private bool _playerOneDead;

		private bool _playerOneAwaitingRevive;

		private bool _playerTwoDead;

		private bool _playerTwoAwaitingRevive;

		private string _playerOneObjectName = "PlayerCharacter";

		private readonly List<Color> _playerOneSpriteColors = new List<Color>();

		private bool _evolutionPickerOpen;

		private int _suppressedPlayerDeathDropCount;

		private bool _previousDumpStateHeld;

		private bool _previousRespawnHeld;

		private bool _previousForceSpawnHeld;

		private bool _previousDamagePlayerTwoHeld;

		private bool _previousDamagePlayerOneHeld;

		private readonly bool[] _previousAttackHeld = new bool[5];

		private float _nextSpawnAttemptAt;

		private float _nextStatusLogAt;

		private float _nextSpawnWaitLogAt;

		private float _nextAiRefreshAt;

		private int _damageOnTouchStateKey;

		private Health _damageOnTouchStateHealth;

		private GameObject _damageOnTouchStateInstigator;

		private float _damageOnTouchStateBeforeHealth;

		private float _damageOnTouchStateFallbackDamage;

		private float _damageOnTouchStateInvincibilityDuration;

		private int _damageOnTouchStateContextualDeathTip;

		private string _damageOnTouchStateSourceName = string.Empty;

		private string _lastSpawnWaitReason = string.Empty;

		private string _playerTwoDamageHudStatus = "P2 DMG: WAIT";

		private string _playerTwoAiHudStatus = "P2 AI: WAIT";

		private string _cameraHudStatus = "CAM: WAIT";

		private bool _debugPlayerOneInputOverride;

		private bool _applyingDiagnosticDamage;

		private Action<ScriptableRenderContext, Camera> _beginCameraRenderingHandler;

		private bool _debugPlayerTwoInputOverride;

		private int _debugPlayerOneGamepadIndex = -1;

		private int _debugPlayerTwoGamepadIndex = -1;

		private Vector2 _debugPlayerOneMove;

		private Vector2 _debugPlayerOneAim = Vector2.right;

		private Vector2 _debugPlayerTwoMove;

		private Vector2 _debugPlayerTwoAim = Vector2.right;

		private bool _debugPlayerTwoDashHeld;

		private bool _debugPlayerTwoInteractHeld;

		private readonly bool[] _debugPlayerTwoAttackHeld = new bool[5];

		private Vector2 _playerOneMove;

		private Vector2 _playerOneAim = Vector2.right;

		private bool _playerOneAimControlled;

		private float _lastPlayerTwoSizePercentage = float.NaN;

		private int _mushroomManagerId;

		private List<MushroomImpactStateInfo> _playerOneMushroomEffects;

		private List<MushroomImpactStateInfo> _playerTwoMushroomEffects;

		private List<MushroomImpactStateInfo> _mushroomEffectsBeforeConsumption;

		private int _mushroomConsumptionRoutingDepth;

		private PlayerCharacter _mushroomConsumerPreviousSingleton;

		private int _mushroomConsumerSingletonDepth;

		private bool _updatingOwnedMushroomEffects;

		private int _lastMushroomEffectUpdatePlayerNumber;

		private BoundGameplayActions _playerOneGameplayActions;

		private BoundGameplayActions _playerTwoGameplayActions;

		private IntPtr _gameplayActionMapPointer;

		private int _gameplayBindingHash;

		private int _playerOneBoundDeviceId = -1;

		private int _playerTwoBoundDeviceId = -1;

		private bool _wasCoopActive;

		public static LocalMultiplayerDriver Instance { get; private set; }

		public PlayerCharacter PlayerOne { get; private set; }

		public PlayerCharacter PlayerTwo { get; private set; }

		public PlayerTwoInputState InputState { get; private set; }

		public Vector2 PlayerOneMoveInput => _playerOneMove;

		public int PlayerOneMushroomEffectCount => _playerOneMushroomEffects?.Count ?? 0;

		public int PlayerTwoMushroomEffectCount => _playerTwoMushroomEffects?.Count ?? 0;

		public int LastMushroomEffectUpdatePlayerNumber => _lastMushroomEffectUpdatePlayerNumber;

		public bool IsPlayerOneDead
		{
			get
			{
				if (!_playerOneAwaitingRevive && !_playerOneDead)
				{
					return IsDead(PlayerOne);
				}
				return true;
			}
		}

		public bool IsPlayerOneRemoved
		{
			get
			{
				if (_playerOneDead)
				{
					return (Object)(object)PlayerOne == (Object)null;
				}
				return false;
			}
		}

		public bool IsPlayerOneAwaitingRevive => _playerOneAwaitingRevive;

		public bool IsPlayerTwoDead
		{
			get
			{
				if (!_playerTwoAwaitingRevive && !_playerTwoDead)
				{
					return IsDead(PlayerTwo);
				}
				return true;
			}
		}

		public bool IsPlayerTwoAwaitingRevive => _playerTwoAwaitingRevive;

		public bool IsEvolutionPickerOpen => _evolutionPickerOpen;

		public int PlayerOneReviveCost => Mathf.Max(0, Plugin.PlayerOneReviveMutagenCost.Value);

		public float PlayerOneReviveHealthFraction => Mathf.Clamp(Plugin.PlayerOneReviveHealthFraction.Value, 0.01f, 1f);

		public int PlayerTwoReviveCost => Mathf.Max(0, Plugin.PlayerTwoReviveMutagenCost.Value);

		public float PlayerTwoReviveHealthFraction => Mathf.Clamp(Plugin.PlayerTwoReviveHealthFraction.Value, 0.01f, 1f);

		public int CurrentMutagenPoints
		{
			get
			{
				if (!((Object)(object)WorldStats.Instance != (Object)null))
				{
					return 0;
				}
				return WorldStats.Instance.CurrentNumMutagenPoints;
			}
		}

		public bool CanRevivePlayerOne
		{
			get
			{
				if (_playerOneAwaitingRevive && _evolutionPickerOpen && IsAlive(PlayerTwo))
				{
					return CurrentMutagenPoints >= PlayerOneReviveCost;
				}
				return false;
			}
		}

		public bool CanRevivePlayerTwo
		{
			get
			{
				if (_playerTwoAwaitingRevive && _evolutionPickerOpen && IsAlive(PlayerOne))
				{
					return CurrentMutagenPoints >= PlayerTwoReviveCost;
				}
				return false;
			}
		}

		public int PendingRevivePlayerNumber
		{
			get
			{
				if (!_playerOneAwaitingRevive)
				{
					if (!_playerTwoAwaitingRevive)
					{
						return 0;
					}
					return 2;
				}
				return 1;
			}
		}

		public int PendingReviveCost
		{
			get
			{
				if (PendingRevivePlayerNumber != 1)
				{
					return PlayerTwoReviveCost;
				}
				return PlayerOneReviveCost;
			}
		}

		public bool CanRevivePendingPlayer
		{
			get
			{
				if (PendingRevivePlayerNumber != 1)
				{
					return CanRevivePlayerTwo;
				}
				return CanRevivePlayerOne;
			}
		}

		public int PlayerOneCharmCount => GetCharmCount(PlayerOne);

		public int PlayerTwoCharmCount => GetCharmCount(PlayerTwo);

		public int SuppressedPlayerDeathDropCount => _suppressedPlayerDeathDropCount;

		public string PlayerTwoDamageHudStatus => _playerTwoDamageHudStatus;

		public string PlayerTwoAiHudStatus => _playerTwoAiHudStatus;

		public string CameraHudStatus => _cameraHudStatus;

		public bool UsesSharedControllerBindingSchema
		{
			get
			{
				BoundGameplayActions playerOneGameplayActions = _playerOneGameplayActions;
				if (playerOneGameplayActions != null && playerOneGameplayActions.IsReady)
				{
					BoundGameplayActions playerTwoGameplayActions = _playerTwoGameplayActions;
					if (playerTwoGameplayActions != null && playerTwoGameplayActions.IsReady)
					{
						return _gameplayActionMapPointer != IntPtr.Zero;
					}
				}
				return false;
			}
		}

		public string ControllerBindingStatus
		{
			get
			{
				if (!UsesSharedControllerBindingSchema)
				{
					return "bindings unresolved; P1=" + (_playerOneGameplayActions?.Describe() ?? "none") + "; P2=" + (_playerTwoGameplayActions?.Describe() ?? "none");
				}
				return $"P1 device {_playerOneBoundDeviceId}: {_playerOneGameplayActions.Describe()} | P2 device {_playerTwoBoundDeviceId}: {_playerTwoGameplayActions.Describe()}";
			}
		}

		public float SharedCameraMidpointError { get; private set; } = float.PositiveInfinity;

		public float RenderCameraMidpointError { get; private set; } = float.PositiveInfinity;

		public bool IsFriendlyFireEnabled => Plugin.FriendlyFireEnabled.Value;

		public bool IsSharedNightVisionActive { get; private set; }

		public float SharedNightVisionCenterError { get; private set; } = float.PositiveInfinity;

		public float SharedNightVisionRadius { get; private set; } = -1f;

		public float SharedNightVisionRequiredRadius { get; private set; } = -1f;

		public float RenderSharedNightVisionCenterError { get; private set; } = float.PositiveInfinity;

		public float RenderSharedNightVisionRadius { get; private set; } = -1f;

		public float RenderSharedNightVisionMaxPlayerDistance { get; private set; } = -1f;

		public Vector2 RenderSharedNightVisionCenter { get; private set; } = new Vector2(float.NaN, float.NaN);

		public Vector2 RenderNightCameraPlayerOneViewport { get; private set; } = new Vector2(float.NaN, float.NaN);

		public Vector2 RenderNightCameraPlayerTwoViewport { get; private set; } = new Vector2(float.NaN, float.NaN);

		public string SharedNightVisionMaterialState { get; private set; } = "none";

		public LocalMultiplayerDriver(IntPtr ptr)
			: base(ptr)
		{
		}//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)


		public LocalMultiplayerDriver()
			: base(ClassInjector.DerivedConstructorPointer<LocalMultiplayerDriver>())
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
		}

		public void SetDebugInputOverride(int playerNumber, Vector2 move, Vector2 aim, bool dashHeld, bool primaryAttackHeld, int attackInputIndex = 0, bool interactHeld = false)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			switch (playerNumber)
			{
			case 1:
				_debugPlayerOneInputOverride = true;
				_debugPlayerOneMove = Vector2.ClampMagnitude(move, 1f);
				_debugPlayerOneAim = ((((Vector2)(ref aim)).sqrMagnitude > 0.001f) ? ((Vector2)(ref aim)).normalized : _playerOneAim);
				break;
			default:
				throw new ArgumentOutOfRangeException("playerNumber", playerNumber, "Debug input only supports player 1 or player 2.");
			case 2:
				_debugPlayerTwoInputOverride = true;
				_debugPlayerTwoMove = Vector2.ClampMagnitude(move, 1f);
				_debugPlayerTwoAim = ((((Vector2)(ref aim)).sqrMagnitude > 0.001f) ? ((Vector2)(ref aim)).normalized : Vector2.right);
				_debugPlayerTwoDashHeld = dashHeld;
				_debugPlayerTwoInteractHeld = interactHeld;
				Array.Clear(_debugPlayerTwoAttackHeld, 0, _debugPlayerTwoAttackHeld.Length);
				if (attackInputIndex < 0 || attackInputIndex >= _debugPlayerTwoAttackHeld.Length)
				{
					throw new ArgumentOutOfRangeException("attackInputIndex", attackInputIndex, "Debug attack input index must be between 0 and 4.");
				}
				_debugPlayerTwoAttackHeld[attackInputIndex] = primaryAttackHeld;
				break;
			}
		}

		public void SetDebugPlayerTwoGamepadIndexOverride(int gamepadIndex)
		{
			_debugPlayerTwoGamepadIndex = Math.Max(0, gamepadIndex);
		}

		public void SetDebugPlayerOneGamepadIndexOverride(int gamepadIndex)
		{
			_debugPlayerOneGamepadIndex = Math.Max(0, gamepadIndex);
		}

		public void ClearDebugPlayerOneGamepadIndexOverride()
		{
			_debugPlayerOneGamepadIndex = -1;
		}

		public void ClearDebugPlayerTwoGamepadIndexOverride()
		{
			_debugPlayerTwoGamepadIndex = -1;
		}

		public void ClearDebugInputOverride(int playerNumber = 0)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (playerNumber == 0 || playerNumber == 1)
			{
				_debugPlayerOneInputOverride = false;
				_debugPlayerOneMove = Vector2.zero;
				_debugPlayerOneAim = Vector2.right;
			}
			if (playerNumber == 0 || playerNumber == 2)
			{
				_debugPlayerTwoInputOverride = false;
				_debugPlayerTwoMove = Vector2.zero;
				_debugPlayerTwoAim = Vector2.right;
				_debugPlayerTwoDashHeld = false;
				_debugPlayerTwoInteractHeld = false;
				Array.Clear(_debugPlayerTwoAttackHeld, 0, _debugPlayerTwoAttackHeld.Length);
			}
		}

		public bool TryApplyDebugMovement(CharacterMovement movement)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)movement == (Object)null)
			{
				return false;
			}
			PlayerCharacter componentInParent = ((Component)movement).GetComponentInParent<PlayerCharacter>();
			if (_debugPlayerOneInputOverride && IsSamePlayer(componentInParent, PlayerOne))
			{
				movement.SetMovement(IsPlayerOneDead ? Vector2.zero : _debugPlayerOneMove);
				return true;
			}
			if (_debugPlayerTwoInputOverride && IsSamePlayer(componentInParent, PlayerTwo))
			{
				movement.SetMovement(IsPlayerTwoDead ? Vector2.zero : _debugPlayerTwoMove);
				return true;
			}
			return false;
		}

		public void ApplyDebugDamage(int playerNumber, bool lethal, string source)
		{
			switch (playerNumber)
			{
			case 1:
				ApplyManualDamage(PlayerOne, PlayerTwo, source, "P1", lethal);
				break;
			case 2:
				ApplyManualDamage(PlayerTwo, PlayerOne, source, "P2", lethal);
				break;
			default:
				throw new ArgumentOutOfRangeException("playerNumber", playerNumber, "Debug damage only supports player 1 or player 2.");
			}
		}

		public void DebugRespawnPlayerTwo(string source)
		{
			ForceRespawnPlayerTwo(source);
		}

		public bool DebugRevivePlayerTwo(string source, out string result)
		{
			return TryRevivePlayerTwo(source, requireEvolutionPicker: false, out result);
		}

		public bool DebugRevivePlayerOne(string source, out string result)
		{
			return TryRevivePlayerOne(source, requireEvolutionPicker: false, out result);
		}

		public void SetEvolutionPickerOpen(bool isOpen)
		{
			_evolutionPickerOpen = isOpen;
		}

		public bool TrySpendMutagenToRevivePlayerTwo(out string result)
		{
			return TryRevivePlayerTwo("level-up UI", requireEvolutionPicker: true, out result);
		}

		public bool TrySpendMutagenToRevivePlayerOne(out string result)
		{
			return TryRevivePlayerOne("level-up UI", requireEvolutionPicker: true, out result);
		}

		public bool TrySpendMutagenToRevivePendingPlayer(out string result)
		{
			return PendingRevivePlayerNumber switch
			{
				1 => TrySpendMutagenToRevivePlayerOne(out result), 
				2 => TrySpendMutagenToRevivePlayerTwo(out result), 
				_ => FailNoPendingRevive(out result), 
			};
		}

		private static bool FailNoPendingRevive(out string result)
		{
			result = "Neither player is awaiting revival.";
			return false;
		}

		public void DebugDumpState(string source)
		{
			DumpState(source);
		}

		public void Awake()
		{
			//IL_0012: 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)
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Scene activeScene = SceneManager.GetActiveScene();
			_sceneHandle = ((Scene)(ref activeScene)).handle;
			_beginCameraRenderingHandler = DelegateSupport.ConvertDelegate<Action<ScriptableRenderContext, Camera>>((Delegate)new Action<ScriptableRenderContext, Camera>(OnBeginCameraRendering));
			RenderPipelineManager.beginCameraRendering += _beginCameraRenderingHandler;
		}

		public void OnDestroy()
		{
			ReleaseBoundGameplayActions();
			if ((Delegate)(object)_beginCameraRenderingHandler != (Delegate)null)
			{
				RenderPipelineManager.beginCameraRendering -= _beginCameraRenderingHandler;
				_beginCameraRenderingHandler = null;
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			if (CoopSession.IsCoopActive)
			{
				Instance?.UpdateSharedCameraFromCamera(camera, renderStage: true);
				Instance?.UpdateSharedNightVision(renderStage: true);
			}
		}

		public void Update()
		{
			CoopSession.ObserveActiveScene();
			ResetForSceneChanges();
			if (!CoopSession.IsCoopActive)
			{
				if (_wasCoopActive || (Object)(object)PlayerOne != (Object)null || (Object)(object)PlayerTwo != (Object)null)
				{
					CleanupPlayerTwoIfPresent();
				}
				_wasCoopActive = false;
				return;
			}
			_wasCoopActive = true;
			ValidateTrackedPlayers();
			LogConnectedGamepadsIfChanged();
			RefreshInput();
			HandleManualControls();
			TrySpawnPlayerTwo();
			RefreshDeathStateFromHealth();
			EnsurePlayerTwoDamageable();
			RefreshPlayerTwoAiTargetingIfDue();
			RefreshPlayerTwoSizeVisuals(force: false);
			MaintainPlayerSingleton();
		}

		public void LateUpdate()
		{
			if (CoopSession.IsCoopActive)
			{
				MaintainPlayerSingleton();
				UpdateLocalPlayerAims();
				EnsureSharedCameraEnforcer(Camera.main);
				UpdateSharedNightVision(renderStage: false);
			}
		}

		public bool IsPlayerTwoComponent(Component component)
		{
			if (!CoopSession.IsCoopActive || (Object)(object)component == (Object)null)
			{
				return false;
			}
			return IsPlayerTwo(ResolveLocalPlayerOwner(component));
		}

		public bool IsPlayerOneComponent(Component component)
		{
			if (!CoopSession.IsCoopActive || (Object)(object)component == (Object)null)
			{
				return false;
			}
			return IsPlayerOne(ResolveLocalPlayerOwner(component));
		}

		public bool IsPlayerOneEvolutionHandler(EvolutionHandler handler)
		{
			if (!CoopSession.IsCoopActive || (Object)(object)handler == (Object)null || _playerOneId == 0)
			{
				return false;
			}
			PlayerCharacter componentInParent = ((Component)handler).GetComponentInParent<PlayerCharacter>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return ((Object)componentInParent).GetInstanceID() == _playerOneId;
			}
			return false;
		}

		public bool IsPlayerTwoEvolutionHandler(EvolutionHandler handler)
		{
			if (!CoopSession.IsCoopActive || (Object)(object)handler == (Object)null || _playerTwoId == 0)
			{
				return false;
			}
			PlayerCharacter componentInParent = ((Component)handler).GetComponentInParent<PlayerCharacter>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return ((Object)componentInParent).GetInstanceID() == _playerTwoId;
			}
			return false;
		}

		public EvolutionHandler GetPlayerOneEvolutionHandler()
		{
			if (!((Object)(object)PlayerOne != (Object)null))
			{
				return null;
			}
			return PlayerOne.PlayerEvolutionHandler;
		}

		public EvolutionHandler GetPlayerTwoEvolutionHandler()
		{
			if (!((Object)(object)PlayerTwo != (Object)null))
			{
				return null;
			}
			return PlayerTwo.PlayerEvolutionHandler;
		}

		public void RefreshPlayerTwoAttackLoadout()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if ((Object)(object)PlayerTwo == (Object)null)
			{
				return;
			}
			try
			{
				RepairPlayerTwoAttackState(PlayerTwo, resetCooldowns: false);
				RepairPlayerTwoDashState(PlayerTwo);
				RefreshPlayerTwoSizeVisuals(force: true);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(75, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to refresh the player-two attack loadout after an evolution change: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				logger.LogWarning(val);
			}
		}

		public void ApplyPlayerTwoMovement(CharacterMovement movement)
		{
			//IL_001e: 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)
			if (IsPlayerTwoDead)
			{
				movement.SetMovement(Vector2.zero);
			}
			else
			{
				movement.SetMovement(InputState.Move);
			}
		}

		public void ApplyPlayerOneMovement(CharacterMovement movement)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			movement.SetMovement(IsPlayerOneDead ? Vector2.zero : _playerOneMove);
		}

		public void HandlePlayerTwoDash(PlayerDashManager dashManager)
		{
			if (!IsPlayerTwoDead)
			{
				if (InputState.DashPressed)
				{
					((CharacterDashManager)dashManager).StartDash();
				}
				if (InputState.DashReleased)
				{
					((CharacterDashManager)dashManager).DashInputReleased();
				}
			}
		}

		public void HandlePlayerTwoAttack(AAttackHandler attackHandler)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (IsPlayerTwoDead)
			{
				return;
			}
			int num = AttackSlotToInputIndex(attackHandler.AttackSlot);
			if (num >= 0)
			{
				if (InputState.AttackPressed[num])
				{
					ApplyPlayerTwoAttackAim(attackHandler);
					((CharacterHandleWeapon)attackHandler).ShootStart();
				}
				if (InputState.AttackReleased[num])
				{
					ApplyPlayerTwoAttackAim(attackHandler);
					((CharacterHandleWeapon)attackHandler).ShootStop();
				}
			}
		}

		public void HandlePlayerTwoInteraction(PlayerInteraction interaction)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			if (IsPlayerTwoDead || (Object)(object)PlayerTwo == (Object)null || !InputState.InteractPressed)
			{
				return;
			}
			IPlayerInteractable val = ((interaction != null) ? interaction.CurrentInteractable : null);
			Burrow currentBurrow = PlayerTwo.CurrentBurrow;
			if (val == null && (Object)(object)currentBurrow != (Object)null)
			{
				val = ((Il2CppObjectBase)currentBurrow).Cast<IPlayerInteractable>();
			}
			if (val == null)
			{
				return;
			}
			Burrow val2 = ((Il2CppObjectBase)val).TryCast<Burrow>();
			if (!val.CanInteract && (!((Object)(object)val2 != (Object)null) || !PlayerTwo.IsInBurrow))
			{
				return;
			}
			PlayerCharacter instance = PlayerCharacter.Instance;
			try
			{
				PlayerCharacter.Instance = PlayerTwo;
				val.InteractWithPlayer();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Player two could not use the focused interactable: ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
				}
				logger.LogWarning(val3);
			}
			finally
			{
				PlayerCharacter.Instance = instance;
			}
		}

		public bool BeginMushroomConsumerUpdate(EdibleItemConsumer consumer)
		{
			PlayerCharacter val = ((consumer != null) ? ((Component)consumer).GetComponentInParent<PlayerCharacter>() : null);
			if (!IsPlayerOne(val) && !IsPlayerTwo(val))
			{
				return false;
			}
			if (_mushroomConsumerSingletonDepth == 0)
			{
				_mushroomConsumerPreviousSingleton = PlayerCharacter.Instance;
			}
			_mushroomConsumerSingletonDepth++;
			PlayerCharacter.Instance = val;
			return true;
		}

		public void EndMushroomConsumerUpdate()
		{
			if (_mushroomConsumerSingletonDepth > 0)
			{
				_mushroomConsumerSingletonDepth--;
				if (_mushroomConsumerSingletonDepth == 0)
				{
					PlayerCharacter.Instance = _mushroomConsumerPreviousSingleton;
					_mushroomConsumerPreviousSingleton = null;
				}
			}
		}

		public bool BeginMushroomEffectCapture(MushroomManager manager)
		{
			PlayerCharacter instance = PlayerCharacter.Instance;
			if ((Object)(object)manager == (Object)null || (!IsPlayerOne(instance) && !IsPlayerTwo(instance)))
			{
				return false;
			}
			EnsureMushroomEffectLists(manager);
			if (_mushroomConsumptionRoutingDepth == 0)
			{
				_mushroomEffectsBeforeConsumption = manager._activeEffects;
			}
			_mushroomConsumptionRoutingDepth++;
			manager._activeEffects = (IsPlayerTwo(instance) ? _playerTwoMushroomEffects : _playerOneMushroomEffects);
			return true;
		}

		public void EndMushroomEffectCapture(MushroomManager manager)
		{
			if (!((Object)(object)manager == (Object)null) && _mushroomConsumptionRoutingDepth > 0)
			{
				_mushroomConsumptionRoutingDepth--;
				if (_mushroomConsumptionRoutingDepth == 0)
				{
					manager._activeEffects = _mushroomEffectsBeforeConsumption ?? _playerOneMushroomEffects;
					_mushroomEffectsBeforeConsumption = null;
				}
			}
		}

		public bool TryUpdateOwnedMushroomEffects(MushroomManager manager)
		{
			if (_updatingOwnedMushroomEffects || (Object)(object)manager == (Object)null || !Plugin.ModEnabled.Value)
			{
				return false;
			}
			if (_playerOneMushroomEffects == null && ((Object)(object)PlayerOne == (Object)null || (Object)(object)PlayerTwo == (Object)null))
			{
				return false;
			}
			EnsureMushroomEffectLists(manager);
			List<MushroomImpactStateInfo> activeEffects = manager._activeEffects;
			PlayerCharacter instance = PlayerCharacter.Instance;
			_updatingOwnedMushroomEffects = true;
			try
			{
				UpdateOwnedMushroomEffects(manager, PlayerOne, _playerOneMushroomEffects, 1);
				UpdateOwnedMushroomEffects(manager, PlayerTwo, _playerTwoMushroomEffects, 2);
			}
			finally
			{
				manager._activeEffects = activeEffects ?? _playerOneMushroomEffects;
				PlayerCharacter.Instance = instance;
				_updatingOwnedMushroomEffects = false;
			}
			return true;
		}

		public bool DebugQueueMushroomEffectForPlayer(int playerNumber, EMushroomEffect effect, out string result)
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			MushroomManager instance = AMonoBehaviourSingleton<MushroomManager>.Instance;
			PlayerCharacter val = (PlayerCharacter)(playerNumber switch
			{
				2 => PlayerTwo, 
				1 => PlayerOne, 
				_ => null, 
			});
			if ((Object)(object)instance == (Object)null || !IsAlive(val))
			{
				result = $"manager={(Object)(object)instance != (Object)null}, P{playerNumber}Alive={IsAlive(val)}.";
				return false;
			}
			EnsureMushroomEffectLists(instance);
			int playerOneMushroomEffectCount = PlayerOneMushroomEffectCount;
			int playerTwoMushroomEffectCount = PlayerTwoMushroomEffectCount;
			PlayerCharacter instance2 = PlayerCharacter.Instance;
			bool flag = false;
			_lastMushroomEffectUpdatePlayerNumber = 0;
			try
			{
				PlayerCharacter.Instance = val;
				flag = BeginMushroomEffectCapture(instance);
				instance.TriggerMushroomEffect(effect, 0f);
			}
			finally
			{
				if (flag)
				{
					EndMushroomEffectCapture(instance);
				}
				PlayerCharacter.Instance = instance2;
			}
			bool flag2 = ((playerNumber != 1) ? (PlayerTwoMushroomEffectCount > playerTwoMushroomEffectCount && PlayerOneMushroomEffectCount == playerOneMushroomEffectCount) : (PlayerOneMushroomEffectCount > playerOneMushroomEffectCount && PlayerTwoMushroomEffectCount == playerTwoMushroomEffectCount));
			result = $"effect={effect}, routed={flag}, P1 effects {playerOneMushroomEffectCount}->{PlayerOneMushroomEffectCount}, P2 effects {playerTwoMushroomEffectCount}->{PlayerTwoMushroomEffectCount}.";
			return flag && flag2;
		}

		public void DebugClearMushroomEffects()
		{
			_playerOneMushroomEffects?.Clear();
			_playerTwoMushroomEffects?.Clear();
			_lastMushroomEffectUpdatePlayerNumber = 0;
		}

		private void EnsureMushroomEffectLists(MushroomManager manager)
		{
			int instanceID = ((Object)manager).GetInstanceID();
			if (_mushroomManagerId != instanceID || _playerOneMushroomEffects == null || _playerTwoMushroomEffects == null)
			{
				_mushroomManagerId = instanceID;
				_playerOneMushroomEffects = manager._activeEffects ?? new List<MushroomImpactStateInfo>();
				_playerTwoMushroomEffects = new List<MushroomImpactStateInfo>();
				_mushroomEffectsBeforeConsumption = null;
				_mushroomConsumptionRoutingDepth = 0;
				_lastMushroomEffectUpdatePlayerNumber = 0;
			}
			else
			{
				List<MushroomImpactStateInfo> activeEffects = manager._activeEffects;
				if (!_updatingOwnedMushroomEffects && _mushroomConsumptionRoutingDepth == 0 && activeEffects != null && ((Il2CppObjectBase)activeEffects).Pointer != ((Il2CppObjectBase)_playerOneMushroomEffects).Pointer && ((Il2CppObjectBase)activeEffects).Pointer != ((Il2CppObjectBase)_playerTwoMushroomEffects).Pointer)
				{
					_playerOneMushroomEffects = activeEffects;
					_playerTwoMushroomEffects = new List<MushroomImpactStateInfo>();
				}
			}
		}

		private void UpdateOwnedMushroomEffects(MushroomManager manager, PlayerCharacter owner, List<MushroomImpactStateInfo> effects, int playerNumber)
		{
			if (effects != null && effects.Count != 0)
			{
				if (!IsAlive(owner))
				{
					effects.Clear();
					return;
				}
				manager._activeEffects = effects;
				PlayerCharacter.Instance = owner;
				_lastMushroomEffectUpdatePlayerNumber = playerNumber;
				manager.UpdateMushroomEffectLogics();
			}
		}

		public void DebugRefreshPlayerTwoSize()
		{
			RefreshPlayerTwoSizeVisuals(force: true);
		}

		public bool IsPlayerTwoGamepadContext(CallbackContext context)
		{
			if (!CoopSession.IsCoopActive)
			{
				return false;
			}
			ReadOnlyArray<Gamepad> all = Gamepad.all;
			int playerTwoGamepadIndex = GetPlayerTwoGamepadIndex();
			if (all.Count <= playerTwoGamepadIndex)
			{
				return false;
			}
			InputControl control = context.control;
			InputDevice val = ((control != null) ? control.device : null);
			if (val == null)
			{
				return false;
			}
			return val.deviceId == ((InputDevice)all[playerTwoGamepadIndex]).deviceId;
		}

		public void RecordFilteredStockInput(CallbackContext context)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (Plugin.DiagnosticsEnabled.Value && !_loggedFilteredStockInput)
			{
				InputControl control = context.control;
				InputDevice val = ((control != null) ? control.device : null);
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(83, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Filtered stock player-one input from player-two device: action=");
					InputAction action = context.action;
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((action != null) ? action.name : null) ?? "unknown");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", control=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((control != null) ? control.path : null) ?? "unknown");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", device=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((val != null) ? ((InputControl)val).displayName : null) ?? ((val != null) ? ((InputControl)val).name : null) ?? "unknown");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
				}
				logger.LogInfo(val2);
				_loggedFilteredStockInput = true;
			}
		}

		public bool ShouldSuppressStockAimInjector(PlayerAttackAimInjector injector)
		{
			if (!TryGetLocalPlayerAim((Component)(object)injector, out var _, out var _))
			{
				return false;
			}
			return true;
		}

		public bool TryApplyLocalPlayerAim(WeaponAim2D weaponAim)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetLocalPlayerAim((Component)(object)weaponAim, out var player, out var aim))
			{
				return false;
			}
			if (IsLocalPlayerDead(player))
			{
				return true;
			}
			ConfigureWeaponAim((WeaponAim)(object)weaponAim, aim, applyRotation: false);
			return true;
		}

		public bool TryApplyLocalPlayerAttackDirection(EICCharacterAttack attack)
		{
			//IL_0020: 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)
			if (!TryGetLocalPlayerAim((Component)(object)attack, out var player, out var aim))
			{
				return false;
			}
			if (IsLocalPlayerDead(player))
			{
				return true;
			}
			ConfigureWeaponAim(attack.WeaponAim, aim, applyRotation: true);
			attack._AimDirectionAtStartOfAttack_k__BackingField = aim;
			return true;
		}

		public bool TryUpdateLocalPlayerAimIndicator(GamepadAimDirection indicator)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetLocalPlayerAim((Component)(object)indicator, out var player, out var aim))
			{
				return false;
			}
			if (IsLocalPlayerDead(player) || (Object)(object)((Component)indicator).gameObject == (Object)null)
			{
				return true;
			}
			if (!((Component)indicator).gameObject.activeSelf)
			{
				((Component)indicator).gameObject.SetActive(true);
			}
			if (!((Behaviour)indicator).enabled)
			{
				((Behaviour)indicator).enabled = true;
			}
			indicator.SetCurrentAim(new Vector2(aim.x, aim.y));
			return true;
		}

		public void UpdateSharedCamera(CombatCamera combatCamera)
		{
			if (CoopSession.IsCoopActive)
			{
				Camera camera = (((Object)(object)combatCamera != (Object)null && (Object)(object)combatCamera.Camera != (Object)null) ? combatCamera.Camera : Camera.main);
				EnsureSharedCameraEnforcer(camera);
				UpdateSharedCameraFromCamera(camera, renderStage: false);
			}
		}

		public void UpdateSharedCameraFromCamera(Camera camera, bool renderStage)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			if (!CoopSession.IsCoopActive || (Object)(object)camera == (Object)null)
			{
				return;
			}
			bool flag = IsAliveForCamera(PlayerOne);
			bool flag2 = IsAliveForCamera(PlayerTwo);
			if (!flag && !flag2)
			{
				_cameraHudStatus = "CAM: NONE";
				return;
			}
			_cameraHudStatus = ((flag && flag2) ? "CAM: BOTH" : (flag2 ? "CAM: P2" : "CAM: P1"));
			Transform transform = ((Component)camera).transform;
			Vector3 val = ((flag && flag2) ? ((((Component)PlayerOne).transform.position + ((Component)PlayerTwo).transform.position) * 0.5f) : (flag2 ? ((Component)PlayerTwo).transform.position : ((Component)PlayerOne).transform.position));
			Vector3 position = transform.position;
			int instanceID = ((Object)camera).GetInstanceID();
			if (!_hasSharedCameraState || _cameraId != instanceID)
			{
				_cameraId = instanceID;
				_baseOrthographicSize = (camera.orthographic ? camera.orthographicSize : 0f);
				_smoothedOrthographicSize = camera.orthographicSize;
				_smoothedCameraCenter = new Vector2(position.x, position.y);
				_hasSharedCameraState = true;
			}
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(val.x, val.y);
			if (renderStage)
			{
				_smoothedCameraCenter = val2;
			}
			else
			{
				float num = 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * Mathf.Max(0.1f, Plugin.CameraFollowLerpSpeed.Value));
				_smoothedCameraCenter = Vector2.Lerp(_smoothedCameraCenter, val2, num);
			}
			transform.position = new Vector3(_smoothedCameraCenter.x, _smoothedCameraCenter.y, position.z);
			SharedCameraMidpointError = Vector2.Distance(new Vector2(transform.position.x, transform.position.y), val2);
			if (renderStage)
			{
				RenderCameraMidpointError = SharedCameraMidpointError;
			}
			if (camera.orthographic)
			{
				float num2 = ((flag && flag2) ? Vector2.Distance(Vector2.op_Implicit(((Component)PlayerOne).transform.position), Vector2.op_Implicit(((Component)PlayerTwo).transform.position)) : 0f);
				float num3 = Mathf.Clamp(Mathf.Max(_baseOrthographicSize, num2 * Mathf.Max(0f, Plugin.CameraDistanceZoomMultiplier.Value) + Mathf.Max(0f, Plugin.CameraZoomPadding.Value)), _baseOrthographicSize, _baseOrthographicSize * Mathf.Max(1f, Plugin.CameraMaxZoomMultiplier.Value));
				float num4 = 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) * Mathf.Max(0.1f, Plugin.CameraZoomLerpSpeed.Value));
				_smoothedOrthographicSize = Mathf.Lerp(_smoothedOrthographicSize, num3, num4);
				camera.orthographicSize = _smoothedOrthographicSize;
			}
		}

		private void EnsureSharedCameraEnforcer(Camera camera)
		{
			if ((Object)(object)camera == (Object)null || (Object)(object)((Component)camera).gameObject == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)camera).GetInstanceID();
			if (_cameraEnforcerId != instanceID || !((Object)(object)((Component)camera).GetComponent<SharedCameraEnforcer>() != (Object)null))
			{
				if ((Object)(object)((Component)camera).GetComponent<SharedCameraEnforcer>() == (Object)null)
				{
					((Component)camera).gameObject.AddComponent<SharedCameraEnforcer>();
				}
				_cameraEnforcerId = instanceID;
			}
		}

		private void UpdateSharedNightVision(bool renderStage)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			if (!CoopSession.IsCoopActive)
			{
				RestoreSharedNightVisionRadius();
				return;
			}
			DayAndNightCycleManager instance = AMonoBehaviourSingleton<DayAndNightCycleManager>.Instance;
			if (!Plugin.SharedNightVisionEnabled.Value || (Object)(object)instance == (Object)null)
			{
				RestoreSharedNightVisionRadius();
				return;
			}
			Camera val = (((Object)(object)Camera.main != (Object)null) ? Camera.main : instance._nightEyesCamera);
			Material nightShaderMaterialToEdit = instance._nightShaderMaterialToEdit;
			if ((Object)(object)nightShaderMaterialToEdit == (Object)null || (Object)(object)val == (Object)null)
			{
				ClearSharedNightVisionTracking();
				return;
			}
			NightVisionMaterialState orRefreshNightVisionMaterialState = GetOrRefreshNightVisionMaterialState(nightShaderMaterialToEdit);
			bool flag = IsAliveForCamera(PlayerOne);
			bool flag2 = IsAliveForCamera(PlayerTwo);
			if (!flag && !flag2)
			{
				RestoreSharedNightVisionRadius();
				return;
			}
			Vector3 val2 = (flag ? val.WorldToViewportPoint(((Component)PlayerOne).transform.position) : val.WorldToViewportPoint(((Component)PlayerTwo).transform.position));
			Vector3 val3 = (flag2 ? val.WorldToViewportPoint(((Component)PlayerTwo).transform.position) : val2);
			Vector3 val4 = ((flag && flag2) ? ((val2 + val3) * 0.5f) : (flag2 ? val3 : val2));
			float num = (val3.x - val2.x) * Mathf.Max(1f, val.aspect);
			float num2 = val3.y - val2.y;
			float num3 = ((flag && flag2) ? (Mathf.Sqrt(num * num + num2 * num2) * 0.5f) : 0f);
			float num4 = ((flag && flag2) ? Mathf.Max(0f, Plugin.SharedNightVisionPadding.Value) : 0f);
			float num5 = Mathf.Max(0f, orRefreshNightVisionMaterialState.BaseViewportRadius + num3 + num4);
			float gradientRadius = Mathf.Max(0f, orRefreshNightVisionMaterialState.BaseGradientRadius + num3 + num4);
			ApplySharedNightVisionToMaterial(nightShaderMaterialToEdit, val4, num5, gradientRadius);
			ApplySharedNightVisionToRendererMaterials(instance, val4, num5, gradientRadius);
			SharedNightVisionRadius = num5;
			SharedNightVisionRequiredRadius = num5;
			Vector4 vector = nightShaderMaterialToEdit.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH);
			SharedNightVisionCenterError = Vector2.Distance(new Vector2(vector.x, vector.y), new Vector2(val4.x, val4.y));
			IsSharedNightVisionActive = flag && flag2;
			if (renderStage)
			{
				RenderSharedNightVisionCenterError = SharedNightVisionCenterError;
				RenderSharedNightVisionRadius = num5;
				RenderSharedNightVisionMaxPlayerDistance = num3;
				RenderSharedNightVisionCenter = new Vector2(val4.x, val4.y);
				RenderNightCameraPlayerOneViewport = new Vector2(val2.x, val2.y);
				RenderNightCameraPlayerTwoViewport = new Vector2(val3.x, val3.y);
				SharedNightVisionMaterialState = DescribeNightVisionMaterials(instance);
			}
		}

		[HideFromIl2Cpp]
		private NightVisionMaterialState GetOrRefreshNightVisionMaterialState(Material material)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)material).GetInstanceID();
			if (!_nightVisionMaterialStates.TryGetValue(instanceID, out var value) || (Object)(object)value.Material == (Object)null)
			{
				value = new NightVisionMaterialState
				{
					Material = material,
					BaseCenter = material.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH),
					BaseViewportRadius = material.GetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH),
					BaseGradientRadius = material.GetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH)
				};
				_nightVisionMaterialStates[instanceID] = value;
			}
			Vector4 vector = material.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH);
			float num = material.GetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH);
			float num2 = material.GetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH);
			if (float.IsNaN(value.LastAppliedCenter.x) || Vector4.Distance(vector, value.LastAppliedCenter) > 0.0001f)
			{
				value.BaseCenter = vector;
			}
			if (float.IsNaN(value.LastAppliedViewportRadius) || !Mathf.Approximately(num, value.LastAppliedViewportRadius))
			{
				value.BaseViewportRadius = num;
			}
			if (float.IsNaN(value.LastAppliedGradientRadius) || !Mathf.Approximately(num2, value.LastAppliedGradientRadius))
			{
				value.BaseGradientRadius = num2;
			}
			return value;
		}

		private void ApplySharedNightVisionToMaterial(Material material, Vector3 center, float viewportRadius, float gradientRadius)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null) && material.HasProperty(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH) && material.HasProperty(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH) && material.HasProperty(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH))
			{
				NightVisionMaterialState orRefreshNightVisionMaterialState = GetOrRefreshNightVisionMaterialState(material);
				material.SetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH, new Vector4(center.x, center.y, 0f, 0f));
				material.SetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH, viewportRadius);
				material.SetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH, gradientRadius);
				orRefreshNightVisionMaterialState.LastAppliedCenter = new Vector4(center.x, center.y, 0f, 0f);
				orRefreshNightVisionMaterialState.LastAppliedViewportRadius = viewportRadius;
				orRefreshNightVisionMaterialState.LastAppliedGradientRadius = gradientRadius;
			}
		}

		private void ApplySharedNightVisionToRendererMaterials(DayAndNightCycleManager manager, Vector3 center, float viewportRadius, float gradientRadius)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object obj;
				if (manager == null)
				{
					obj = null;
				}
				else
				{
					UniversalRendererData universalRendererData = manager._universalRendererData;
					obj = ((universalRendererData != null) ? ((ScriptableRendererData)universalRendererData).rendererFeatures : null);
				}
				List<ScriptableRendererFeature> val = (List<ScriptableRendererFeature>)obj;
				if (val != null)
				{
					for (int i = 0; i < val.Count; i++)
					{
						ScriptableRendererFeature obj2 = val[i];
						FullScreenPassRendererFeature val2 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast<FullScreenPassRendererFeature>() : null);
						ApplySharedNightVisionToMaterial((val2 != null) ? val2.passMaterial : null, center, viewportRadius, gradientRadius);
					}
				}
			}
			catch (Exception ex)
			{
				if (Plugin.DiagnosticsEnabled.Value)
				{
					ManualLogSource logger = Plugin.Logger;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(47, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Unable to update all night renderer materials: ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val3);
				}
			}
		}

		private string DescribeNightVisionMaterials(DayAndNightCycleManager manager)
		{
			List<string> list = new List<string>();
			AddNightVisionMaterialDescription(list, "manager", (manager != null) ? manager._nightShaderMaterialToEdit : null);
			try
			{
				object obj;
				if (manager == null)
				{
					obj = null;
				}
				else
				{
					UniversalRendererData universalRendererData = manager._universalRendererData;
					obj = ((universalRendererData != null) ? ((ScriptableRendererData)universalRendererData).rendererFeatures : null);
				}
				List<ScriptableRendererFeature> val = (List<ScriptableRendererFeature>)obj;
				if (val != null)
				{
					for (int i = 0; i < val.Count; i++)
					{
						ScriptableRendererFeature obj2 = val[i];
						FullScreenPassRendererFeature val2 = ((obj2 != null) ? ((Il2CppObjectBase)obj2).TryCast<FullScreenPassRendererFeature>() : null);
						if ((Object)(object)((val2 != null) ? val2.passMaterial : null) != (Object)null && val2.passMaterial.HasProperty(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH))
						{
							AddNightVisionMaterialDescription(list, $"feature[{i}]", val2.passMaterial);
						}
					}
				}
			}
			catch (Exception ex)
			{
				list.Add("renderer-error=" + ex.Message);
			}
			if (list.Count <= 0)
			{
				return "none";
			}
			return string.Join("; ", list);
		}

		private static void AddNightVisionMaterialDescription(List<string> descriptions, string source, Material material)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material == (Object)null)
			{
				descriptions.Add(source + "=null");
				return;
			}
			Vector4 vector = material.GetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH);
			float value = material.GetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH);
			float value2 = material.GetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH);
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(30, 8);
			defaultInterpolatedStringHandler.AppendFormatted(source);
			defaultInterpolatedStringHandler.AppendLiteral("=");
			defaultInterpolatedStringHandler.AppendFormatted(((Object)material).name);
			defaultInterpolatedStringHandler.AppendLiteral("#");
			defaultInterpolatedStringHandler.AppendFormatted(((Object)material).GetInstanceID());
			defaultInterpolatedStringHandler.AppendLiteral(" shader=");
			Shader shader = material.shader;
			defaultInterpolatedStringHandler.AppendFormatted(((shader != null) ? ((Object)shader).name : null) ?? "null");
			defaultInterpolatedStringHandler.AppendLiteral(" center=(");
			defaultInterpolatedStringHandler.AppendFormatted(vector.x, "0.000");
			defaultInterpolatedStringHandler.AppendLiteral(",");
			defaultInterpolatedStringHandler.AppendFormatted(vector.y, "0.000");
			defaultInterpolatedStringHandler.AppendLiteral(") radius=");
			defaultInterpolatedStringHandler.AppendFormatted(value, "0.000");
			defaultInterpolatedStringHandler.AppendLiteral("/");
			defaultInterpolatedStringHandler.AppendFormatted(value2, "0.000");
			descriptions.Add(defaultInterpolatedStringHandler.ToStringAndClear());
		}

		private void RestoreSharedNightVisionRadius()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			float num = RestoreNightVisionMaterials();
			IsSharedNightVisionActive = false;
			SharedNightVisionCenterError = float.PositiveInfinity;
			SharedNightVisionRadius = num;
			SharedNightVisionRequiredRadius = num;
			RenderSharedNightVisionCenterError = float.PositiveInfinity;
			RenderSharedNightVisionRadius = num;
			RenderSharedNightVisionMaxPlayerDistance = -1f;
			RenderSharedNightVisionCenter = new Vector2(float.NaN, float.NaN);
			RenderNightCameraPlayerOneViewport = new Vector2(float.NaN, float.NaN);
			RenderNightCameraPlayerTwoViewport = new Vector2(float.NaN, float.NaN);
			SharedNightVisionMaterialState = "none";
		}

		private void ClearSharedNightVisionTracking()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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)
			RestoreNightVisionMaterials();
			_nightVisionMaterialStates.Clear();
			IsSharedNightVisionActive = false;
			SharedNightVisionCenterError = float.PositiveInfinity;
			SharedNightVisionRadius = -1f;
			SharedNightVisionRequiredRadius = -1f;
			RenderSharedNightVisionCenterError = float.PositiveInfinity;
			RenderSharedNightVisionRadius = -1f;
			RenderSharedNightVisionMaxPlayerDistance = -1f;
			RenderSharedNightVisionCenter = new Vector2(float.NaN, float.NaN);
			RenderNightCameraPlayerOneViewport = new Vector2(float.NaN, float.NaN);
			RenderNightCameraPlayerTwoViewport = new Vector2(float.NaN, float.NaN);
			SharedNightVisionMaterialState = "none";
		}

		private float RestoreNightVisionMaterials()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			float num = -1f;
			foreach (NightVisionMaterialState value in _nightVisionMaterialStates.Values)
			{
				if (!((Object)(object)value.Material == (Object)null))
				{
					value.Material.SetVector(DayAndNightCycleManager.VIEWPORT_CENTER_SHADER_PARAM_HASH, value.BaseCenter);
					value.Material.SetFloat(DayAndNightCycleManager.VIEWPORT_RADIUS_SHADER_PARAM_HASH, value.BaseViewportRadius);
					value.Material.SetFloat(DayAndNightCycleManager.GRADIENT_RADIUS_SHADER_PARAM_HASH, value.BaseGradientRadius);
					value.LastAppliedCenter = new Vector4(float.NaN, float.NaN, float.NaN, float.NaN);
					value.LastAppliedViewportRadius = float.NaN;
					value.LastAppliedGradientRadius = float.NaN;
					if (num < 0f)
					{
						num = value.BaseViewportRadius;
					}
				}
			}
			return num;
		}

		public void RestorePlayerOneSingletonIfNeeded(PlayerCharacter candidate)
		{
			if (!((Object)(object)candidate == (Object)null) && _playerTwoId != 0 && _playerOneId != 0 && ((Object)candidate).GetInstanceID() == _playerTwoId && (Object)(object)PlayerOne != (Object)null && !IsPlayerOneDead)
			{
				PlayerCharacter.Instance = PlayerOne;
			}
		}

		public bool TryHandlePlayerDeath(PlayerCharacter player, Health health)
		{
			if (!Plugin.ModEnabled.Value || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (IsPlayerTwoComponent((Component)(object)player))
			{
				if (!Plugin.PreventPlayerTwoDeathRunEnd.Value || !Plugin.ContinueRunWhileAnyPlayerAlive.Value || !IsAlive(PlayerOne))
				{
					return false;
				}
				MarkPlayerDead(player, health, isPlayerTwo: true);
				if (Plugin.RemovePlayerTwoOnDeath.Value)
				{
					RemovePlayerTwoAfterDeath(player);
				}
				PlayerCharacter.Instance = PlayerOne;
				MaintainPlayerSingleton();
				_playerTwoDamageHudStatus = "P2 DMG: DEAD";
				_cameraHudStatus = "CAM: P1";
				Plugin.Logger.LogInfo((object)(Plugin.RemovePlayerTwoOnDeath.Value ? "Player two died; removed P2's world entity and opened the revive slot while P1 remains alive." : "Player two died; leaving P2 dead and suppressing the single-player run-end flow while P1 is alive."));
				return true;
			}
			if (!IsPlayerOne(player) || !Plugin.ContinueRunWhileAnyPlayerAlive.Value || !IsAlive(PlayerTwo))
			{
				return false;
			}
			CapturePlayerOneVisualState(player);
			_playerOneAwaitingRevive = true;
			MarkPlayerDead(player, health, isPlayerTwo: false);
			TransferEvolutionProgressToPlayerTwo();
			PlayerCharacter.Instance = PlayerTwo;
			if (Plugin.RemovePlayerOneOnDeath.Value)
			{
				RemovePlayerOneAfterDeath(player);
			}
			NotifyNearbyAiAboutPlayer(PlayerTwo, "player one death fallback", logSummary: true);
			MaintainPlayerSingleton();
			_cameraHudStatus = "CAM: P2";
			Plugin.Logger.LogInfo((object)(Plugin.RemovePlayerOneOnDeath.Value ? "Player one died while P2 is alive; removed P1's world entity and handed camera, XP, and level-up ownership to P2." : "Player one died while P2 is alive; suppressing the single-player run-end flow and shifting control/camera singleton to P2."));
			return true;
		}

		public bool ShouldSuppressLocalPlayerFoodDrop(DropItemsOnDeath dropItemsOnDeath)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			if (!Plugin.ModEnabled.Value || !Plugin.SuppressPlayerFoodDrops.Value || (Object)(object)dropItemsOnDeath == (Object)null)
			{
				return false;
			}
			PlayerCharacter componentInParent = ((Component)dropItemsOnDeath).GetComponentInParent<PlayerCharacter>();
			bool flag = (Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).gameObject != (Object)null && ((Object)((Component)componentInParent).gameObject).name.StartsWith("LocalMultiplayer_Player2", StringComparison.Ordinal);
			bool flag2 = (Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).gameObject != (Object)null && ((Object)((Component)componentInParent).gameObject).name.StartsWith("LocalMultiplayer_Player1_PendingDestroy", StringComparison.Ordinal);
			if (!IsPlayerOne(componentInParent) && !IsPlayerTwoComponent((Component)(object)componentInParent) && !flag && !flag2)
			{
				return false;
			}
			_suppressedPlayerDeathDropCount++;
			if (Plugin.DiagnosticsEnabled.Value)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag3 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(68, 2, ref flag3);
				if (flag3)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Suppressed player death food drop for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)componentInParent).name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; total suppressed callbacks=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_suppressedPlayerDeathDropCount);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				logger.LogInfo(val);
			}
			return true;
		}

		public bool ShouldForcePlayerTwoDamageable(Health health)
		{
			if (!Plugin.ModEnabled.Value || !Plugin.ForcePlayerTwoDamageEnabled.Value || (Object)(object)health == (Object)null || IsPlayerTwoDead)
			{
				return false;
			}
			if (!IsPlayerTwoComponent((Component)(object)health))
			{
				return false;
			}
			ClearDamageLocks(health);
			return true;
		}

		public bool TryForcePlayerTwoDamageOutput(Health health, float requestedDamage, float computedDamage, out float forcedDamage)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			forcedDamage = computedDamage;
			if (!Plugin.ModEnabled.Value || !Plugin.ForcePlayerTwoDamageEnabled.Value || (Object)(object)health == (Object)null || IsPlayerTwoDead || requestedDamage <= 0f || computedDamage > 0f || !IsPlayerTwoComponent((Component)(object)health))
			{
				return false;
			}
			ClearDamageLocks(health);
			forcedDamage = requestedDamage;
			if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOutputOverride)
			{
				_loggedPlayerTwoDamageOutputOverride = true;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(113, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Forced player-two damage output from ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(computedDamage);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(forcedDamage);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; a cloned resistance/avoidance rule had zeroed a positive incoming hit.");
				}
				logger.LogInfo(val);
			}
			return true;
		}

		internal void BeforePlayerTwoDamageOnTouchCollision(DamageOnTouch damageOnTouch, Collider2D otherCollider)
		{
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			ClearDamageOnTouchState();
			if (!Plugin.ModEnabled.Value || (Object)(object)damageOnTouch == (Object)null || (Object)(object)otherCollider == (Object)null || (Object)(object)PlayerTwo == (Object)null || IsPlayerTwoDead || !IsPlayerTwoComponent((Component)(object)otherCollider))
			{
				return;
			}
			try
			{
				if (IsSamePlayer(ResolveLocalPlayerDamageSource(damageOnTouch), PlayerTwo))
				{
					return;
				}
				EnsurePlayerTwoHitCollider(PlayerTwo);
				Health health = ((AStatCharacter<PlayerStats>)(object)PlayerTwo).Health;
				if ((Object)(object)health != (Object)null)
				{
					ClearDamageLocks(health);
				}
				RemovePlayerTwoFromDamageIgnoreList(damageOnTouch, otherCollider, health);
				IncludePlayerTwoLayerInDamageMask(damageOnTouch, otherCollider);
				LogPlayerTwoDamageOnTouchCollision(damageOnTouch, otherCollider, health);
				if (!((Object)(object)health == (Object)null) && !(health.CurrentHealth <= 0f))
				{
					float damageOnTouchFallbackDamage = GetDamageOnTouchFallbackDamage(damageOnTouch);
					if (!(damageOnTouchFallbackDamage <= 0f) && CanDamageOnTouchReachPlayerTwo(damageOnTouch, otherCollider))
					{
						_damageOnTouchStateKey = BuildDamageOnTouchStateKey(damageOnTouch, otherCollider);
						_damageOnTouchStateHealth = health;
						_damageOnTouchStateBeforeHealth = health.CurrentHealth;
						_damageOnTouchStateFallbackDamage = damageOnTouchFallbackDamage;
						_damageOnTouchStateInvincibilityDuration = Mathf.Max(0f, damageOnTouch.InvincibilityDuration);
						_damageOnTouchStateContextualDeathTip = damageOnTouch.ContextualDeathTip;
						_damageOnTouchStateInstigator = GetDamageOnTouchInstigator(damageOnTouch);
						_damageOnTouchStateSourceName = ((Object)damageOnTouch).name;
					}
				}
			}
			catch (Exception ex)
			{
				if (Plugin.DiagnosticsEnabled.Value)
				{
					ManualLogSource logger = Plugin.Logger;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(63, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed while preparing player two for DamageOnTouch collision: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
			}
		}

		internal void AfterPlayerTwoDamageOnTouchCollision(DamageOnTouch damageOnTouch, Collider2D otherCollider)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			if (_damageOnTouchStateKey == 0 || (Object)(object)damageOnTouch == (Object)null || (Object)(object)otherCollider == (Object)null || _damageOnTouchStateKey != BuildDamageOnTouchStateKey(damageOnTouch, otherCollider) || (Object)(object)_damageOnTouchStateHealth == (Object)null || (Object)(object)PlayerTwo == (Object)null)
			{
				return;
			}
			Health damageOnTouchStateHealth = _damageOnTouchStateHealth;
			float damageOnTouchStateBeforeHealth = _damageOnTouchStateBeforeHealth;
			float damageOnTouchStateFallbackDamage = _damageOnTouchStateFallbackDamage;
			float damageOnTouchStateInvincibilityDuration = _damageOnTouchStateInvincibilityDuration;
			int damageOnTouchStateContextualDeathTip = _damageOnTouchStateContextualDeathTip;
			GameObject damageOnTouchStateInstigator = _damageOnTouchStateInstigator;
			string damageOnTouchStateSourceName = _damageOnTouchStateSourceName;
			ClearDamageOnTouchState();
			float currentHealth = damageOnTouchStateHealth.CurrentHealth;
			if (currentHealth < damageOnTouchStateBeforeHealth - 0.001f)
			{
				RecordPlayerTwoDamageResult(damageOnTouchStateHealth, "DamageOnTouch(" + damageOnTouchStateSourceName + ")", damageOnTouchStateBeforeHealth - currentHealth, damageOnTouchStateBeforeHealth);
			}
			else
			{
				if (IsPlayerTwoDead)
				{
					return;
				}
				bool flag = default(bool);
				try
				{
					ClearDamageLocks(damageOnTouchStateHealth);
					float currentHealth2 = damageOnTouchStateHealth.CurrentHealth;
					damageOnTouchStateHealth.Damage(damageOnTouchStateFallbackDamage, damageOnTouchStateInstigator, damageOnTouchStateInvincibilityDuration, damageOnTouchStateContextualDeathTip);
					damageOnTouchStateHealth.UpdateHealthBar(true);
					if (Plugin.DiagnosticsEnabled.Value && !_loggedPlayerTwoDamageOnTouchFallback)
					{
						_loggedPlayerTwoDamageOnTouchFallback = true;
						ManualLogSource logger = Plugin.Logger;
						BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(111, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Applied player-two DamageOnTouch fallback from ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(damageOnTouchStateSourceName);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; the normal touch-damage path saw P2 but left health unchanged.");
						}
						logger.LogInfo(val);
					}
					RecordPlayerTwoDamageResult(damageOnTouchStateHealth, "DamageOnTouch fallback(" + damageOnTouchStateSourceName + ")", damageOnTouchStateFallbackDamage, currentHealth2);
				}
				catch (Exception ex)
				{
					if (Plugin.DiagnosticsEnabled.Value)
					{
						ManualLogSource logger2 = Plugin.Logger;
						BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(57, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed while applying player-two DamageOnTouch fallback: ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
						}
						logger2.LogWarning(val2);
					}
				}
			}
		}

		public bool IsPlayerTwoAttackableEntity(IAttackableEntity entity)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			if (!Plugin.ModEnabled.Value || entity == null || (Object)(object)PlayerTwo == (Object)null || IsPlayerTwoDead)
			{
				return false;
			}
			try
			{
				Health health = entity.Health;
				Health health2 = ((AStatCharacter<PlayerStats>)(object)PlayerTwo).Health;
				return (Object)(object)health != (Object)null && (Object)(object)health2 != (Object)null && ((Object)health).GetInstanceID() == ((Object)health2).GetInstanceID();
			}
			catch (Exception ex)
			{
				if (Plugin.DiagnosticsEnabled.Value)
				{
					ManualLogSource logger = Plugin.Logger;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to compare attackable entity to player two: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogWarning(val);
				}
				return false;
			}
		}

		public bool IsPlayerOneAttackableEntity(IAttackableEntity entity)
		{
			return IsPlayerAttackableEntity(entity, PlayerOne, IsPlayerOneDead);
		}

		public bool TryOverrideLocalPlayerAllyStatus(AIDetectionController controller, IAttackableEntity target, out bool isAlly)
		{
			isAlly = false;
			if ((Object)(object)controller == (Object)null || target == null)
			{
				return false;
			}
			bool num = IsPlayerOneAttackableEntity(target);
			bool flag = IsPlayerTwoAttackableEntity(target);
			if (!num && !flag)
			{
				return false;
			}
			if (IsAiCharmedByLocalPlayer(controller))
			{
				is