Decompiled source of CouchCrew v1.0.0

plugins/CouchCrew.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Users;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CouchCrew")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0")]
[assembly: AssemblyProduct("CouchCrew")]
[assembly: AssemblyTitle("CouchCrew")]
[assembly: AssemblyVersion("0.2.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 CouchCrew
{
	public enum CreditCorner
	{
		TopLeft,
		TopRight,
		BottomLeft,
		BottomRight
	}
	internal static class CouchCredit
	{
		private static GameObject _go;

		private static RawImage _raw;

		private static RectTransform _rt;

		private static Canvas _canvas;

		private static Texture2D _tex;

		private static bool _created;

		private static bool _failed;

		private static CreditCorner _appliedCorner = (CreditCorner)(-1);

		private static float _appliedWidth = float.NaN;

		private static Type _shiftMgrType;

		private static FieldInfo _fPhase;

		private static Object _shiftMgr;

		private static bool _reflTried;

		private static float _nextPhaseCheck;

		private static float _nextCamCheck;

		private static bool _inShift;

		private static MethodInfo _miUiCam;

		private static bool _uiCamTried;

		internal static void Tick()
		{
			if (_failed)
			{
				return;
			}
			if (Plugin.ShowTwitchCredit == null || !Plugin.ShowTwitchCredit.Value)
			{
				if ((Object)(object)_go != (Object)null && _go.activeSelf)
				{
					_go.SetActive(false);
				}
				return;
			}
			try
			{
				if (!_created)
				{
					Create();
				}
				if (!((Object)(object)_go == (Object)null))
				{
					MaintainCamera();
					ApplyCorner();
					UpdatePhase();
					bool flag = !_inShift;
					if (_go.activeSelf != flag)
					{
						_go.SetActive(flag);
					}
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Plugin.Log.LogWarning((object)("[credit] " + ex.Message));
			}
		}

		private static void Create()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_008a: 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)
			_created = true;
			_tex = LoadPng();
			if ((Object)(object)_tex == (Object)null)
			{
				_failed = true;
				Plugin.Log.LogWarning((object)"[credit] credit.png not found next to the DLL — credit disabled.");
				return;
			}
			_go = new GameObject("CouchCrew.CreditCanvas");
			Object.DontDestroyOnLoad((Object)(object)_go);
			_canvas = _go.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 29500;
			_go.AddComponent<CanvasScaler>().uiScaleMode = (ScaleMode)0;
			GameObject val = new GameObject("Image");
			val.transform.SetParent(_go.transform, false);
			_raw = val.AddComponent<RawImage>();
			_raw.texture = (Texture)(object)_tex;
			((Graphic)_raw).raycastTarget = false;
			_rt = ((Graphic)_raw).rectTransform;
			SetLayerRecursive(_go.transform, 5);
			Plugin.Log.LogInfo((object)("[credit] canvas created (credit.png " + ((Texture)_tex).width + "x" + ((Texture)_tex).height + ")."));
		}

		private static void MaintainCamera()
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			if ((Object)(object)_canvas == (Object)null || Time.unscaledTime < _nextCamCheck)
			{
				return;
			}
			_nextCamCheck = Time.unscaledTime + 1f;
			if (!_uiCamTried)
			{
				_uiCamTried = true;
				Type type = AccessTools.TypeByName("GameUtil");
				_miUiCam = ((type != null) ? AccessTools.Method(type, "get_uiCamera", (Type[])null, (Type[])null) : null);
			}
			Camera val = null;
			try
			{
				val = (Camera)((_miUiCam != null) ? /*isinst with value type is only supported in some contexts*/: null);
			}
			catch
			{
			}
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)_canvas.worldCamera != (Object)(object)val || (int)_canvas.renderMode != 1)
				{
					_canvas.renderMode = (RenderMode)1;
					_canvas.worldCamera = val;
					_canvas.planeDistance = Mathf.Max(val.nearClipPlane + 0.5f, 1f);
				}
			}
			else if ((int)_canvas.renderMode != 0)
			{
				_canvas.renderMode = (RenderMode)0;
				_canvas.worldCamera = null;
			}
		}

		private static void UpdatePhase()
		{
			if (Time.unscaledTime < _nextPhaseCheck)
			{
				return;
			}
			_nextPhaseCheck = Time.unscaledTime + 1f;
			if (!_reflTried)
			{
				_reflTried = true;
				_shiftMgrType = AccessTools.TypeByName("ShiftManager");
				_fPhase = ((_shiftMgrType != null) ? AccessTools.Field(_shiftMgrType, "_shiftPhase") : null);
			}
			if (_fPhase == null)
			{
				_inShift = false;
				return;
			}
			try
			{
				if (_shiftMgr == (Object)null)
				{
					_shiftMgr = Object.FindObjectOfType(_shiftMgrType);
				}
				_inShift = _shiftMgr != (Object)null && Convert.ToInt32(_fPhase.GetValue(_shiftMgr)) == 3;
			}
			catch
			{
				_inShift = false;
			}
		}

		private static Texture2D LoadPng()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			try
			{
				string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
				string text = (string.IsNullOrEmpty(directoryName) ? null : Path.Combine(directoryName, "credit.png"));
				if (text == null || !File.Exists(text))
				{
					return null;
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text)))
				{
					return null;
				}
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				return val;
			}
			catch
			{
				return null;
			}
		}

		private static void ApplyCorner()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rt == (Object)null) && !((Object)(object)_tex == (Object)null))
			{
				CreditCorner creditCorner = ((Plugin.CreditCornerCfg != null) ? Plugin.CreditCornerCfg.Value : CreditCorner.TopLeft);
				float num = ((Plugin.CreditWidth != null) ? Plugin.CreditWidth.Value : 320f);
				if (creditCorner != _appliedCorner || num != _appliedWidth)
				{
					_appliedCorner = creditCorner;
					_appliedWidth = num;
					bool flag = creditCorner == CreditCorner.TopLeft || creditCorner == CreditCorner.BottomLeft;
					bool flag2 = creditCorner == CreditCorner.TopLeft || creditCorner == CreditCorner.TopRight;
					Vector2 val = default(Vector2);
					((Vector2)(ref val))..ctor(flag ? 0f : 1f, flag2 ? 1f : 0f);
					RectTransform rt = _rt;
					RectTransform rt2 = _rt;
					Vector2 val2 = (_rt.pivot = val);
					Vector2 anchorMin = (rt2.anchorMax = val2);
					rt.anchorMin = anchorMin;
					float num2 = 12f;
					_rt.anchoredPosition = new Vector2(flag ? num2 : (0f - num2), flag2 ? (0f - num2) : num2);
					_rt.sizeDelta = new Vector2(num, num * (float)((Texture)_tex).height / (float)Mathf.Max(1, ((Texture)_tex).width));
				}
			}
		}

		private static void SetLayerRecursive(Transform t, int layer)
		{
			((Component)t).gameObject.layer = layer;
			for (int i = 0; i < t.childCount; i++)
			{
				SetLayerRecursive(t.GetChild(i), layer);
			}
		}
	}
	internal static class CouchMenu
	{
		private class Item
		{
			public string label;

			public ConfigEntry<string> cfg;

			public Action action;
		}

		internal static bool IsOpen;

		private static Item[] _items;

		private static GameObject _go;

		private static object _text;

		private static object _shadow;

		private static bool _ready;

		private static bool _failed;

		private static Type _tmpType;

		private static Type _imgType;

		private static PropertyInfo _fontProp;

		private static object _font;

		private static int _sel;

		private static ConfigEntry<string> _capTarget;

		private static string _capLabel;

		private static bool _prevUp;

		private static bool _prevDown;

		private static bool _prevA;

		private static bool _capWait;

		private static bool _stateLogged;

		private static MethodInfo _miUiCam;

		private static bool _uiCamTried;

		private static void BuildItems()
		{
			if (_items == null)
			{
				_items = new Item[11]
				{
					new Item
					{
						label = "Resume",
						action = Close
					},
					new Item
					{
						label = "Change Color",
						action = CouchCoop.CycleCouchColor
					},
					new Item
					{
						label = "Brake/Reverse",
						cfg = Plugin.P2BrakeButton
					},
					new Item
					{
						label = "Drift",
						cfg = Plugin.P2DriftButton
					},
					new Item
					{
						label = "Boost",
						cfg = Plugin.P2BoostButton
					},
					new Item
					{
						label = "Grab/Throw",
						cfg = Plugin.P2GrabButton
					},
					new Item
					{
						label = "Lift/Lower",
						cfg = Plugin.P2LiftButton
					},
					new Item
					{
						label = "Use Tool",
						cfg = Plugin.P2ToolButton
					},
					new Item
					{
						label = "Beep",
						cfg = Plugin.P2BeepButton
					},
					new Item
					{
						label = "Place Station",
						cfg = Plugin.P2PlaceButton
					},
					new Item
					{
						label = "Leave Game",
						action = delegate
						{
							Close();
							CouchCoop.LeaveCouch();
						}
					}
				};
			}
		}

		internal static void HandleStartPress()
		{
			if (!IsOpen)
			{
				Open();
			}
			else if (_capTarget != null)
			{
				_capTarget = null;
				Redraw();
			}
			else
			{
				Close();
			}
		}

		internal static void Open()
		{
			DestroyUi();
			if (EnsureUi())
			{
				BuildItems();
				IsOpen = true;
				_sel = 0;
				_capTarget = null;
				_prevUp = (_prevDown = true);
				_prevA = true;
				_stateLogged = false;
				_go.SetActive(true);
				Redraw();
				NetworkIdentity localPlayer = NetworkClient.localPlayer;
				Plugin.Log.LogInfo((object)("[p2menu] opened (fresh UI). localPlayer=" + (((Object)(object)localPlayer != (Object)null) ? (((Object)localPlayer).name + "#" + localPlayer.netId) : "null") + " isCouch=" + ((Object)(object)localPlayer != (Object)null && CouchCoop.CouchBodies.Contains(localPlayer)) + "."));
			}
		}

		private static void DestroyUi()
		{
			if (!((Object)(object)_go == (Object)null))
			{
				try
				{
					Object.Destroy((Object)(object)_go);
				}
				catch
				{
				}
				_go = null;
				_text = null;
				_shadow = null;
				_ready = false;
			}
		}

		private static void LogOpenState()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			if (_stateLogged || (Object)(object)_go == (Object)null)
			{
				return;
			}
			_stateLogged = true;
			try
			{
				Canvas component = _go.GetComponent<Canvas>();
				StringBuilder stringBuilder = new StringBuilder("[p2menu] live state: ");
				stringBuilder.Append("screen=").Append(Screen.width).Append("x")
					.Append(Screen.height);
				if ((Object)(object)component != (Object)null)
				{
					stringBuilder.Append(" mode=").Append(component.renderMode).Append(" display=")
						.Append(component.targetDisplay)
						.Append(" scaleFactor=")
						.Append(component.scaleFactor.ToString("0.00"))
						.Append(" pixelRect=")
						.Append(((object)component.pixelRect/*cast due to .constrained prefix*/).ToString());
				}
				StringBuilder stringBuilder2 = stringBuilder.Append(" rootLossyScale=");
				Vector3 lossyScale = _go.transform.lossyScale;
				stringBuilder2.Append(((Vector3)(ref lossyScale)).ToString("0.00"));
				for (int i = 0; i < _go.transform.childCount; i++)
				{
					Transform child = _go.transform.GetChild(i);
					RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null);
					if (!((Object)(object)val == (Object)null))
					{
						StringBuilder stringBuilder3 = stringBuilder.Append(" | ").Append(((Object)val).name).Append(" lossy=");
						lossyScale = ((Transform)val).lossyScale;
						StringBuilder stringBuilder4 = stringBuilder3.Append(((Vector3)(ref lossyScale)).ToString("0.00")).Append(" anchor=");
						Vector2 val2 = val.anchorMin;
						StringBuilder stringBuilder5 = stringBuilder4.Append(((Vector2)(ref val2)).ToString("0.00")).Append(" pos=");
						val2 = val.anchoredPosition;
						stringBuilder5.Append(((Vector2)(ref val2)).ToString("0"));
					}
				}
				Plugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			catch
			{
			}
		}

		internal static void Close()
		{
			IsOpen = false;
			_capTarget = null;
			if ((Object)(object)_go != (Object)null)
			{
				_go.SetActive(false);
			}
		}

		internal static void Tick()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				return;
			}
			if (CouchCoop.CouchBodies.Count == 0)
			{
				Close();
				return;
			}
			LogOpenState();
			ReadOnlyArray<Gamepad> all = Gamepad.all;
			if (all.Count < 2)
			{
				Close();
				return;
			}
			Gamepad val = all[1];
			if (_capTarget != null)
			{
				TickCapture(val);
				return;
			}
			float num = ((val.leftStick != null) ? ((InputControl<Vector2>)(object)val.leftStick).ReadValue().y : 0f);
			bool flag = (val.dpad != null && val.dpad.up.isPressed) || num > 0.6f;
			bool flag2 = (val.dpad != null && val.dpad.down.isPressed) || num < -0.6f;
			bool flag3 = val.buttonSouth != null && val.buttonSouth.isPressed;
			if (flag && !_prevUp)
			{
				_sel = (_sel + _items.Length - 1) % _items.Length;
				Redraw();
			}
			if (flag2 && !_prevDown)
			{
				_sel = (_sel + 1) % _items.Length;
				Redraw();
			}
			if (flag3 && !_prevA)
			{
				Activate();
			}
			_prevUp = flag;
			_prevDown = flag2;
			_prevA = flag3;
		}

		private static void Activate()
		{
			Item item = _items[_sel];
			if (item.action != null)
			{
				item.action();
				if (IsOpen)
				{
					Redraw();
				}
			}
			else
			{
				_capTarget = item.cfg;
				_capLabel = item.label;
				_capWait = true;
				Redraw();
			}
		}

		private static void TickCapture(Gamepad pad)
		{
			ButtonControl val = FirstPressed(pad);
			if (_capWait)
			{
				if (val == null)
				{
					_capWait = false;
				}
			}
			else if (val != null)
			{
				_capTarget.Value = ((InputControl)val).name;
				CouchCoop.InvalidateP2ButtonCache();
				Plugin.Log.LogInfo((object)("[p2menu] bound '" + _capLabel + "' to '" + ((InputControl)val).name + "'."));
				_capTarget = null;
				Redraw();
			}
		}

		private static ButtonControl FirstPressed(Gamepad pad)
		{
			foreach (ButtonControl item in Candidates(pad))
			{
				if (item != null && item.isPressed)
				{
					return item;
				}
			}
			return null;
		}

		private static IEnumerable<ButtonControl> Candidates(Gamepad pad)
		{
			yield return pad.buttonNorth;
			yield return pad.buttonEast;
			yield return pad.buttonWest;
			yield return pad.buttonSouth;
			yield return pad.leftShoulder;
			yield return pad.rightShoulder;
			yield return pad.leftTrigger;
			yield return pad.rightTrigger;
			yield return pad.leftStickButton;
			yield return pad.rightStickButton;
			yield return pad.selectButton;
			if (pad.dpad != null)
			{
				yield return pad.dpad.up;
				yield return pad.dpad.down;
				yield return pad.dpad.left;
				yield return pad.dpad.right;
			}
		}

		private static void Redraw()
		{
			string s;
			if (_capTarget != null)
			{
				s = "<b>PLAYER 2</b>\n\nPress a button on controller 2\nto use for " + _capLabel.ToUpperInvariant() + "\n\n(Start = cancel)";
			}
			else
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("<b>PLAYER 2</b>\n\n");
				for (int i = 0; i < _items.Length; i++)
				{
					stringBuilder.Append((i == _sel) ? "> " : "   ").Append(_items[i].label);
					if (_items[i].cfg != null)
					{
						stringBuilder.Append(": ").Append(_items[i].cfg.Value);
					}
					stringBuilder.Append('\n');
				}
				stringBuilder.Append("\n(A = select, Start = close)");
				s = stringBuilder.ToString();
			}
			SetText(_shadow, s);
			SetText(_text, s);
		}

		private static bool EnsureUi()
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: 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_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			if (_ready)
			{
				return true;
			}
			if (_failed)
			{
				return false;
			}
			try
			{
				_tmpType = AccessTools.TypeByName("TMPro.TextMeshProUGUI");
				if (_tmpType == null)
				{
					_failed = true;
					Plugin.Log.LogWarning((object)"[p2menu] TMP type not found.");
					return false;
				}
				_fontProp = _tmpType.GetProperty("font");
				Object[] array = Resources.FindObjectsOfTypeAll(_tmpType);
				foreach (Object obj in array)
				{
					Component val = (Component)(object)((obj is Component) ? obj : null);
					if (!((Object)(object)val != (Object)null))
					{
						continue;
					}
					Scene scene = val.gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						_font = ((_fontProp != null) ? _fontProp.GetValue(val) : null);
						if (_font != null)
						{
							break;
						}
					}
				}
				_go = new GameObject("CouchCrew_P2Menu");
				Object.DontDestroyOnLoad((Object)(object)_go);
				Canvas val2 = _go.AddComponent<Canvas>();
				Camera val3 = ResolveUiCamera();
				if ((Object)(object)val3 != (Object)null)
				{
					val2.renderMode = (RenderMode)1;
					val2.worldCamera = val3;
					val2.planeDistance = Mathf.Max(val3.nearClipPlane + 0.5f, 1f);
				}
				else
				{
					val2.renderMode = (RenderMode)0;
				}
				val2.sortingOrder = 28000;
				Vector2 val4 = (Plugin.SplitStacked.Value ? new Vector2(0.5f, 0.25f) : new Vector2(0.75f, 0.5f));
				_imgType = AccessTools.TypeByName("UnityEngine.UI.Image");
				if (_imgType != null)
				{
					GameObject val5 = new GameObject("Bg");
					val5.transform.SetParent(_go.transform, false);
					Component obj2 = val5.AddComponent(_imgType);
					PropertyInfo property = _imgType.GetProperty("color");
					if (property != null)
					{
						property.SetValue(obj2, (object)new Color(0f, 0f, 0f, 0.78f), null);
					}
					RectTransform component = val5.GetComponent<RectTransform>();
					Vector2 val6 = (component.pivot = val4);
					Vector2 anchorMin = (component.anchorMax = val6);
					component.anchorMin = anchorMin;
					component.anchoredPosition = Vector2.zero;
					component.sizeDelta = new Vector2(430f, 520f);
				}
				_shadow = MakeText("Shadow", val4, new Vector2(3f, -3f), new Color(0f, 0f, 0f, 0.6f));
				_text = MakeText("Text", val4, Vector2.zero, Color.white);
				SetLayerRecursive(_go.transform, 5);
				_go.SetActive(false);
				_ready = true;
				Plugin.Log.LogInfo((object)("[p2menu] created (font=" + (_font != null) + ", uiCam=" + (((Object)(object)val3 != (Object)null) ? ((Object)val3).name : "none — overlay fallback") + ")."));
				return true;
			}
			catch (Exception ex)
			{
				_failed = true;
				Plugin.Log.LogWarning((object)("[p2menu] setup: " + ex.Message));
				return false;
			}
		}

		private static Camera ResolveUiCamera()
		{
			try
			{
				if (!_uiCamTried)
				{
					_uiCamTried = true;
					Type type = AccessTools.TypeByName("GameUtil");
					_miUiCam = ((type != null) ? AccessTools.Method(type, "get_uiCamera", (Type[])null, (Type[])null) : null);
				}
				return (Camera)((_miUiCam != null) ? /*isinst with value type is only supported in some contexts*/: null);
			}
			catch
			{
				return null;
			}
		}

		private static void SetLayerRecursive(Transform t, int layer)
		{
			((Component)t).gameObject.layer = layer;
			for (int i = 0; i < t.childCount; i++)
			{
				SetLayerRecursive(t.GetChild(i), layer);
			}
		}

		private static object MakeText(string name, Vector2 anchor, Vector2 pos, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_006b: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(_go.transform, false);
			Component val2 = val.AddComponent(_tmpType);
			if (_font != null && _fontProp != null)
			{
				_fontProp.SetValue(val2, _font);
			}
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val3 = (component.pivot = anchor);
			Vector2 anchorMin = (component.anchorMax = val3);
			component.anchorMin = anchorMin;
			component.anchoredPosition = pos;
			component.sizeDelta = new Vector2(400f, 500f);
			SetProp(val2, "fontSize", 22f);
			SetProp(val2, "color", color);
			SetProp(val2, "richText", true);
			SetEnumProp(val2, "alignment", "TopLeft");
			return val2;
		}

		private static void SetText(object tmp, string s)
		{
			if (tmp == null)
			{
				return;
			}
			try
			{
				PropertyInfo property = tmp.GetType().GetProperty("text");
				if (property != null && property.CanWrite)
				{
					property.SetValue(tmp, s, null);
				}
			}
			catch
			{
			}
		}

		private static void SetProp(object o, string prop, object val)
		{
			try
			{
				PropertyInfo property = o.GetType().GetProperty(prop);
				if (property != null && property.CanWrite)
				{
					property.SetValue(o, val, null);
				}
			}
			catch
			{
			}
		}

		private static void SetEnumProp(object o, string prop, string enumName)
		{
			try
			{
				PropertyInfo property = o.GetType().GetProperty(prop);
				if (property != null)
				{
					property.SetValue(o, Enum.Parse(property.PropertyType, enumName), null);
				}
			}
			catch
			{
			}
		}
	}
	[BepInPlugin("com.hunter.couchcrew", "Couch Crew", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.hunter.couchcrew";

		public const string Name = "Couch Crew";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<KeyCode> ProbeKey;

		internal static ConfigEntry<KeyCode> SpawnKey;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> DemuxInput;

		internal static ConfigEntry<bool> RawDriveInput;

		internal static ConfigEntry<bool> CamFrameBoth;

		internal static ConfigEntry<float> CamZoom;

		internal static ConfigEntry<bool> FixTransition;

		internal static ConfigEntry<float> TransitionSpacing;

		internal static ConfigEntry<int> TransitionDelayFrames;

		internal static ConfigEntry<bool> SplitScreen;

		internal static ConfigEntry<bool> SplitStacked;

		internal static ConfigEntry<bool> JoinOnStart;

		internal static ConfigEntry<string> P2ToolButton;

		internal static ConfigEntry<string> P2BeepButton;

		internal static ConfigEntry<string> P2BrakeButton;

		internal static ConfigEntry<string> P2DriftButton;

		internal static ConfigEntry<string> P2BoostButton;

		internal static ConfigEntry<string> P2GrabButton;

		internal static ConfigEntry<string> P2LiftButton;

		internal static ConfigEntry<string> P2PlaceButton;

		internal static ConfigEntry<bool> ShowTwitchCredit;

		internal static ConfigEntry<CreditCorner> CreditCornerCfg;

		internal static ConfigEntry<float> CreditWidth;

		internal static ConfigEntry<bool> PerPlayerNameplates;

		internal static ConfigEntry<bool> PerPlayerShopItems;

		internal static ConfigEntry<bool> PerPlayerTransactions;

		internal static ConfigEntry<bool> PerPlayerHazardIcons;

		private void Awake()
		{
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Expected O, but got Unknown
			//IL_03d8: Expected O, but got Unknown
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			ProbeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Probe", "DumpKey", (KeyCode)290, "Press in-game to re-dump the couch-coop internals. The probe also auto-dumps once a player body is driving, so this is optional (and a no-op if legacy Input is unavailable).");
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "Enabled", true, "PoC #1 master switch. When on, the SpawnKey spawns an extra forklift body owned by the host and forces its isLocalPlayer=true. Host-only. EXPERIMENTAL.");
			SpawnKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("CouchCoop", "SpawnKey", (KeyCode)288, "Host-only: press during an active shift to spawn ONE extra couch forklift body (PoC #1). (Avoid F10 — Windows binds it to search.)");
			JoinOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "JoinOnStart", true, "Player 2 can press Start on the SECOND controller during an active shift to hop in, no keyboard needed (same as pressing the SpawnKey). Host-only. After joining, Start opens the P2 menu (resume / change color / rebind buttons / leave).");
			P2ToolButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2ToolButton", "rightShoulder", "Controller-2 button that uses held tools (blower/extinguisher/vacuum/scrubber). Rebindable in-game from the P2 menu (Start after joining).");
			P2BeepButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2BeepButton", "buttonNorth", "Controller-2 button for the horn/beep. Rebindable in-game from the P2 menu.");
			P2BrakeButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2BrakeButton", "buttonEast", "Controller-2 button for brake/reverse. Rebindable in-game from the P2 menu.");
			P2DriftButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2DriftButton", "leftTrigger", "Controller-2 button for drift. Rebindable in-game from the P2 menu.");
			P2BoostButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2BoostButton", "buttonSouth", "Controller-2 button for boost/nitro. Rebindable in-game from the P2 menu.");
			P2GrabButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2GrabButton", "auto", "Controller-2 button for grab/throw. 'auto' = use the game's own binding. Rebindable in-game from the P2 menu.");
			P2LiftButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2LiftButton", "auto", "Controller-2 button for lift/lower. 'auto' = use the game's own binding. Rebindable in-game from the P2 menu.");
			P2PlaceButton = ((BaseUnityPlugin)this).Config.Bind<string>("CouchCoop", "P2PlaceButton", "dpadDown", "Controller-2 button for placing/picking up stations. Rebindable in-game from the P2 menu.");
			ShowTwitchCredit = ((BaseUnityPlugin)this).Config.Bind<bool>("Credit", "ShowTwitchCredit", true, "Show the small 'CouchCrew by izaya_here' logo in the corner (menu, lobby and break room only, hidden during shifts). Set to false to hide it.");
			CreditCornerCfg = ((BaseUnityPlugin)this).Config.Bind<CreditCorner>("Credit", "Corner", CreditCorner.TopLeft, "Which screen corner the credit logo sits in.");
			CreditWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Credit", "ImageWidth", 320f, "On-screen width (pixels) of the credit logo.");
			DemuxInput = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "DemuxInput", true, "Route gamepad #2 to the couch body (independent driving) instead of mirroring P1's input. Needs 2 gamepads connected. Restricts P1's input to exclude gamepad #2 while active.");
			RawDriveInput = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "RawDriveInput", true, "Driving demux mode. TRUE (default): raw gamepad-2 read written into P2's VehicleInput (the only reliable demux — Unity input getters read the ACTIVE device, so the getter path mirrors P1). FALSE: let the game's getters run (will sync to whoever moved last). Keep this TRUE.");
			CamFrameBoth = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "CamFrameBoth", true, "Shared-screen camera: keep ALL player forklifts in frame (recenters on their midpoint and zooms out as they spread apart). Only active while a couch body exists.");
			CamZoom = ((BaseUnityPlugin)this).Config.Bind<float>("CouchCoop", "CamZoom", 2f, "How hard the shared camera zooms out as players spread apart (higher = further back). Tune to taste.");
			FixTransition = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "FixTransition", true, "Bring the couch body along on the break-room->shift transition. The game teleports ONE body per network connection, so the couch body (which shares the host connection) would otherwise be left behind in the break room when the shift loads. This re-teleports it next to the host.");
			TransitionSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("CouchCoop", "TransitionSpacing", 2f, "Sideways gap (metres, to the host's right) the couch body is placed at after a transition so the two bodies don't spawn stacked on each other.");
			SplitScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "SplitScreen", true, "EXPERIMENTAL true splitscreen: P1 and P2 each get half the screen, rendered DIRECT to screen (bypasses the game's fullscreen render-texture blit, so the scaled/FXAA post path is skipped — slightly rawer image). Overrides CamFrameBoth when on. If the screen goes black or breaks, set this to false to fall back to the shared zoom-out camera.");
			SplitStacked = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "SplitStacked", false, "Split TOP/BOTTOM (true: P1 top, P2 bottom) instead of LEFT/RIGHT (false: P1 left, P2 right).");
			PerPlayerNameplates = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "PerPlayerNameplates", true, "Duplicate the player name labels onto each player's half of the splitscreen. Without this the nameplates only project onto P1's half. Turn off if nameplates misbehave.");
			PerPlayerShopItems = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "PerPlayerShopItems", true, "Duplicate the shop item name/description popups onto each half so both players see them while shopping. Turn off if shop popups misbehave.");
			PerPlayerTransactions = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "PerPlayerTransactions", true, "Duplicate the money popups (the +$/-$ that appears when buying or selling) onto each half. Turn off if money popups misbehave.");
			PerPlayerHazardIcons = ((BaseUnityPlugin)this).Config.Bind<bool>("CouchCoop", "PerPlayerHazardIcons", true, "Duplicate the hazard effect icons so each player sees their OWN active hazards on their half. Turn off if hazard icons misbehave.");
			TransitionDelayFrames = ((BaseUnityPlugin)this).Config.Bind<int>("CouchCoop", "TransitionDelayFrames", 240, "SAFETY CAP (frames) on the post-transition re-anchor. After a transition the couch body is dragged to the host until the HOST stops moving (it glides to the shift over ~1s, not an instant snap), then released to drive freely. This caps that follow in case the host never settles (~4s at 60fps).");
			Harmony val = new Harmony("com.hunter.couchcrew");
			Probe.PatchAll(val);
			CouchCoop.PatchAll(val);
			Log.LogInfo((object)("Couch Crew 1.0.0 loaded. P2 joins with Start on controller 2 during a shift " + $"(or {SpawnKey.Value}); {ProbeKey.Value}=probe dump."));
		}
	}
	internal static class Probe
	{
		private static bool _ready;

		private static Type _camCtrlType;

		private static Type _vehicleType;

		private static Type _inputMgrType;

		private static Type _aggroInputType;

		private static FieldInfo _fCam;

		private static FieldInfo _fInputStatic;

		private static PropertyInfo _pAsset;

		private static object _camCtrl;

		private static readonly List<object> _vehicles = new List<object>();

		private static int _firstTickFrame = -1;

		private static int _lastPollFrame = -1;

		private static bool _tickLogged;

		private static bool _inputBroken;

		private static bool _loggedPath;

		private static string DumpPath
		{
			get
			{
				try
				{
					return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "CouchCrew-probe.txt");
				}
				catch
				{
					return "CouchCrew-probe.txt";
				}
			}
		}

		internal static void PatchAll(Harmony h)
		{
			Init();
			Patch(h, _camCtrlType, "OnUpdatePresentation", "Post_CamTick");
			Patch(h, _vehicleType, "OnUpdateSimulation", "Post_Vehicle");
		}

		private static void Patch(Harmony h, Type t, string method, string postfixName)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			if (t == null)
			{
				Plugin.Log.LogWarning((object)("[probe] type not found for ." + method + " — skipped."));
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(t, method, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				Plugin.Log.LogWarning((object)("[probe] " + t.Name + "." + method + " not found — skipped."));
			}
			else
			{
				MethodInfo method2 = typeof(Probe).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic);
				h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)("[probe] patched " + t.Name + "." + method));
			}
		}

		private static void Init()
		{
			if (!_ready)
			{
				_ready = true;
				_camCtrlType = AccessTools.TypeByName("CameraController");
				_vehicleType = AccessTools.TypeByName("VehicleController");
				_inputMgrType = AccessTools.TypeByName("AggroInputManager");
				_aggroInputType = AccessTools.TypeByName("AggroInput");
				if (_camCtrlType != null)
				{
					_fCam = AccessTools.Field(_camCtrlType, "_cam");
				}
				if (_inputMgrType != null)
				{
					_fInputStatic = AccessTools.Field(_inputMgrType, "input");
				}
				if (_aggroInputType != null)
				{
					_pAsset = AccessTools.Property(_aggroInputType, "asset");
				}
			}
		}

		private static void Post_CamTick(object __instance)
		{
			//IL_0051: 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)
			_camCtrl = __instance;
			if (!_tickLogged)
			{
				_tickLogged = true;
				Plugin.Log.LogInfo((object)"[probe] tick active (CameraController.OnUpdatePresentation).");
			}
			int frameCount = Time.frameCount;
			if (frameCount == _lastPollFrame)
			{
				return;
			}
			_lastPollFrame = frameCount;
			if (_firstTickFrame < 0)
			{
				_firstTickFrame = frameCount;
			}
			if (!_inputBroken)
			{
				try
				{
					if (Input.GetKeyDown(Plugin.ProbeKey.Value))
					{
						Dump("hotkey");
					}
					if (Plugin.Enabled.Value && Input.GetKeyDown(Plugin.SpawnKey.Value))
					{
						CouchCoop.SpawnCouchBody();
					}
				}
				catch (Exception ex)
				{
					_inputBroken = true;
					Plugin.Log.LogWarning((object)("[probe] legacy Input unavailable (" + ex.GetType().Name + ") — hotkeys off; using auto-dump only."));
				}
			}
			CouchCoop.TickJoinButton();
			CouchMenu.Tick();
			CouchCredit.Tick();
		}

		private static void Post_Vehicle(object __instance)
		{
			foreach (object vehicle in _vehicles)
			{
				if (vehicle == __instance)
				{
					return;
				}
			}
			if (_vehicles.Count < 12)
			{
				_vehicles.Add(__instance);
			}
		}

		internal static void Dump(string trigger)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("================ CouchCrew probe (" + trigger + ")  frame=" + Time.frameCount + " ================");
			try
			{
				DumpDevices(stringBuilder);
			}
			catch (Exception ex)
			{
				stringBuilder.AppendLine("[devices] ERROR: " + ex);
			}
			try
			{
				DumpInputMaps(stringBuilder);
			}
			catch (Exception ex2)
			{
				stringBuilder.AppendLine("[inputmaps] ERROR: " + ex2);
			}
			try
			{
				DumpNetwork(stringBuilder);
			}
			catch (Exception ex3)
			{
				stringBuilder.AppendLine("[network] ERROR: " + ex3);
			}
			try
			{
				DumpCameras(stringBuilder);
			}
			catch (Exception ex4)
			{
				stringBuilder.AppendLine("[cameras] ERROR: " + ex4);
			}
			try
			{
				DumpLocalBody(stringBuilder);
			}
			catch (Exception ex5)
			{
				stringBuilder.AppendLine("[localbody] ERROR: " + ex5);
			}
			stringBuilder.AppendLine("================ end probe ================");
			string text = stringBuilder.ToString();
			Plugin.Log.LogInfo((object)text);
			try
			{
				File.AppendAllText(DumpPath, text);
			}
			catch (Exception ex6)
			{
				Plugin.Log.LogWarning((object)("[probe] file write failed: " + ex6.Message));
			}
			if (!_loggedPath)
			{
				_loggedPath = true;
				Plugin.Log.LogInfo((object)("[probe] dump file: " + DumpPath));
			}
		}

		private static void DumpDevices(StringBuilder sb)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			sb.AppendLine("--- 1. INPUT DEVICES (InputSystem.devices) ---");
			int num = 0;
			int num2 = 0;
			Enumerator<InputDevice> enumerator = InputSystem.devices.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputDevice current = enumerator.Current;
					num2++;
					bool flag = current is Gamepad;
					if (flag)
					{
						num++;
					}
					sb.AppendLine("  [" + (flag ? "GAMEPAD" : ((object)current).GetType().Name) + "] name='" + ((InputControl)current).name + "' display='" + ((InputControl)current).displayName + "' layout='" + ((InputControl)current).layout + "' added=" + current.added);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			sb.AppendLine("  TOTALS: " + num2 + " devices, " + num + " gamepad(s).  (couch coop needs >=2 input sources)");
		}

		private static void DumpInputMaps(StringBuilder sb)
		{
			//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_00a6: 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)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			sb.AppendLine("--- 2. AGGROINPUT ACTION MAPS (.enabled) ---");
			if (_fInputStatic == null)
			{
				sb.AppendLine("AggroInputManager.input field not found.");
				return;
			}
			object value = _fInputStatic.GetValue(null);
			if (value == null)
			{
				sb.AppendLine("AggroInputManager.input is null (input not initialized yet).");
				return;
			}
			if (_pAsset == null)
			{
				sb.AppendLine("AggroInput.asset property not found.");
				return;
			}
			object? value2 = _pAsset.GetValue(value);
			InputActionAsset val = (InputActionAsset)((value2 is InputActionAsset) ? value2 : null);
			if ((Object)(object)val == (Object)null)
			{
				sb.AppendLine("AggroInput.asset is null / not an InputActionAsset.");
				return;
			}
			sb.AppendLine("  asset='" + ((Object)val).name + "'  control schemes: " + DescribeSchemes(val));
			Enumerator<InputActionMap> enumerator = val.actionMaps.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputActionMap current = enumerator.Current;
					int num = 0;
					try
					{
						if (current.devices.HasValue)
						{
							num = current.devices.Value.Count;
						}
					}
					catch
					{
					}
					sb.AppendLine("  map '" + current.name + "'  enabled=" + current.enabled + "  actions=" + current.actions.Count + "  boundDevices=" + num);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			sb.AppendLine("  (Expect: Game enabled; Game1/Game2/Game3 present but disabled — those are the spare per-player maps we'd bind controller #2+ to.)");
		}

		private static string DescribeSchemes(InputActionAsset asset)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			try
			{
				Enumerator<InputControlScheme> enumerator = asset.controlSchemes.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InputControlScheme current = enumerator.Current;
						if (stringBuilder.Length > 0)
						{
							stringBuilder.Append(", ");
						}
						stringBuilder.Append(((InputControlScheme)(ref current)).name);
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			catch
			{
				return "<unavailable>";
			}
			if (stringBuilder.Length <= 0)
			{
				return "<none>";
			}
			return stringBuilder.ToString();
		}

		private static void DumpNetwork(StringBuilder sb)
		{
			sb.AppendLine("--- 3. NETWORK / OWNERSHIP (Mirror) ---");
			sb.AppendLine("  NetworkServer.active=" + NetworkServer.active + "  NetworkClient.active=" + NetworkClient.active + "  isHost=" + (NetworkServer.active && NetworkClient.active));
			NetworkIdentity localPlayer = NetworkClient.localPlayer;
			sb.AppendLine("  NetworkClient.localPlayer = " + IdName(localPlayer) + "   (the ONE isLocalPlayer body this process drives)");
			if (!NetworkServer.active)
			{
				sb.AppendLine("  server not active (client-only / not in a hosted run) — connection table is host-side only.");
				return;
			}
			sb.AppendLine("  NetworkServer.connections.Count = " + NetworkServer.connections.Count);
			foreach (KeyValuePair<int, NetworkConnectionToClient> connection in NetworkServer.connections)
			{
				NetworkConnectionToClient value = connection.Value;
				int num = 0;
				try
				{
					num = ((((NetworkConnection)value).owned != null) ? ((NetworkConnection)value).owned.Count : 0);
				}
				catch
				{
				}
				sb.AppendLine("  conn #" + connection.Key + "  identity=" + IdName(((NetworkConnection)value).identity) + "  owned=" + num);
				try
				{
					if (((NetworkConnection)value).owned == null)
					{
						continue;
					}
					foreach (NetworkIdentity item in ((NetworkConnection)value).owned)
					{
						sb.AppendLine("      owns: " + IdName(item) + ((item == localPlayer) ? "   <-- localPlayer" : ""));
					}
				}
				catch (Exception ex)
				{
					sb.AppendLine("      <owned enumerate error: " + ex.Message + ">");
				}
			}
			sb.AppendLine("  (Confirms: one controllable body per connection. A 2nd couch body would be an EXTRA owned identity on the host connection whose isLocalPlayer we force true.)");
		}

		private static string IdName(NetworkIdentity id)
		{
			if ((Object)(object)id == (Object)null)
			{
				return "<null>";
			}
			try
			{
				return "'" + ((Object)id).name + "' netId=" + id.netId;
			}
			catch
			{
				return "netId?";
			}
		}

		private static void DumpCameras(StringBuilder sb)
		{
			sb.AppendLine("--- 4. CAMERA RIG ---");
			if (_camCtrl != null && _fCam != null)
			{
				object? value = _fCam.GetValue(_camCtrl);
				Camera val = (Camera)((value is Camera) ? value : null);
				sb.AppendLine("  CameraController._cam = " + (((Object)(object)val != (Object)null) ? DescribeCamera(val) : "<null>"));
				if ((Object)(object)val != (Object)null)
				{
					List<string> list = new List<string>();
					Component[] components = ((Component)val).gameObject.GetComponents<Component>();
					foreach (Component val2 in components)
					{
						list.Add(((object)val2).GetType().Name);
					}
					sb.AppendLine("    camera GO components (what drives the scaled RenderTexture?): " + string.Join(", ", list.ToArray()));
				}
			}
			else
			{
				sb.AppendLine("  CameraController not captured / _cam field missing.");
			}
			sb.AppendLine("  All cameras (" + Camera.allCamerasCount + "):");
			Camera[] allCameras = Camera.allCameras;
			foreach (Camera cam in allCameras)
			{
				sb.AppendLine("    " + DescribeCamera(cam));
			}
			sb.AppendLine("  (Splitscreen = clone this rig per player and set Camera.rect viewports; watch for a targetTexture/URP render-texture path that may not compose with rect.)");
		}

		private static string DescribeCamera(Camera cam)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cam == (Object)null)
			{
				return "<null>";
			}
			Rect rect = cam.rect;
			return "go='" + ((Object)((Component)cam).gameObject).name + "' enabled=" + ((Behaviour)cam).enabled + " depth=" + cam.depth + " rect=(" + ((Rect)(ref rect)).x.ToString("0.##") + "," + ((Rect)(ref rect)).y.ToString("0.##") + "," + ((Rect)(ref rect)).width.ToString("0.##") + "," + ((Rect)(ref rect)).height.ToString("0.##") + ") targetTexture=" + (((Object)(object)cam.targetTexture != (Object)null) ? ((Object)cam.targetTexture).name : "<null>") + " cullingMask=0x" + cam.cullingMask.ToString("X");
		}

		private static void DumpLocalBody(StringBuilder sb)
		{
			sb.AppendLine("--- 5. LOCAL PLAYER BODY (captured VehicleControllers) ---");
			if (_vehicles.Count == 0)
			{
				sb.AppendLine("  none captured yet (no forklift has run OnUpdateSimulation).");
				return;
			}
			int num = 0;
			foreach (object vehicle in _vehicles)
			{
				num++;
				Component val = (Component)((vehicle is Component) ? vehicle : null);
				if ((Object)(object)val == (Object)null)
				{
					sb.AppendLine("  [" + num + "] <not a Component>");
					continue;
				}
				GameObject gameObject = val.gameObject;
				NetworkIdentity component = val.GetComponent<NetworkIdentity>();
				sb.AppendLine("  [" + num + "] go='" + ((Object)gameObject).name + "'  " + IdName(component) + (((Object)(object)component != (Object)null) ? ("  isLocalPlayer=" + component.isLocalPlayer + "  connToClient=" + ((component.connectionToClient != null) ? component.connectionToClient.connectionId.ToString() : "<null>")) : ""));
				List<string> list = new List<string>();
				Component[] components = gameObject.GetComponents<Component>();
				for (int i = 0; i < components.Length; i++)
				{
					string name = ((object)components[i]).GetType().Name;
					if (name.StartsWith("Player") || name == "VehicleController" || name == "NitroController")
					{
						list.Add(name);
					}
				}
				sb.AppendLine("      player components: " + string.Join(", ", list.ToArray()));
			}
			sb.AppendLine("  (This is the body+component set a 2nd couch player must replicate & have driven locally.)");
		}
	}
	internal static class CouchCoop
	{
		internal static readonly HashSet<NetworkIdentity> CouchBodies = new HashSet<NetworkIdentity>();

		private const int PocBodyCap = 1;

		private static MethodInfo _serverGetSpawnedPlayer;

		private static Harmony _harmony;

		private static Type _vehicleType;

		private static FieldInfo _vehInputField;

		private static PropertyInfo _aggroAssetProp;

		private static object _p2Input;

		private static bool _demuxReady;

		private static bool _demuxFailed;

		private const int ReapplyFrames = 15;

		private static int _reapplyLeft;

		private static Type _entityType;

		private static MethodInfo _miGetNetTransform;

		private static FieldInfo _fNitroInput;

		private static bool _actionPatchesApplied;

		private static ButtonControl _toolBtnCache;

		private static ButtonControl _beepBtnCache;

		private static ButtonControl _brakeBtnCache;

		private static ButtonControl _driftBtnCache;

		private static ButtonControl _boostBtnCache;

		private static ButtonControl _grabBtnCache;

		private static ButtonControl _liftBtnCache;

		private static ButtonControl _placeBtnCache;

		private static bool _btnCacheValid;

		private static Type _stripNitroType;

		private static MethodInfo _miStripActivate;

		private static FieldInfo _fStripTransform;

		private static FieldInfo _fStripBounds;

		private static FieldInfo _fStripNitroActive;

		private static object _hintsClone;

		private static MethodInfo _miHintLate;

		private static Camera _hintCam;

		private static bool _hintReentry;

		private static bool _hintSwapped;

		private static NetworkIdentity _savedLP;

		private static MethodInfo _miSetLocalPlayer;

		private static FieldInfo _fLocalPlayerField;

		private static bool _lpResolved;

		private static MethodInfo _miUpdateFloaters;

		private static Camera _floaterCam;

		private static bool _floaterReentry;

		private static Type _floaterUIType;

		private static Type _entityBehaviourBaseType;

		private static FieldInfo _fFloatersList;

		private static FieldInfo _fFloTargetPos;

		private static FieldInfo _fFloOffset;

		private static FieldInfo _fFloVisible;

		private static FieldInfo _fFloAlwaysVis;

		private static FieldInfo _fFloOnScreen;

		private static FieldInfo _fFloScale;

		private static bool _floaterFieldsReady;

		private static bool _floaterFailed;

		private static GameObject _floaterHolder;

		private static readonly Dictionary<object, object> _floaterClones = new Dictionary<object, object>();

		private static Type _nameplateType;

		private static MethodInfo _miNameplateLate;

		private static Camera _nameplateCam;

		private static bool _npReentry;

		private static FieldInfo _fNpPlayer;

		private static FieldInfo _fNpPlayerEntity;

		private static FieldInfo _fNpColorMgr;

		private static FieldInfo _fNpContainer;

		private static FieldInfo _fNpNameText;

		private static bool _npFieldsReady;

		private static readonly Dictionary<object, object> _nameplateClones = new Dictionary<object, object>();

		private static Type _shopItemType;

		private static MethodInfo _miShopItemUpdate;

		private static Camera _shopItemCam;

		private static bool _siReentry;

		private static bool _siSwapped;

		private static NetworkIdentity _siSavedLP;

		private static FieldInfo _fSiContainer;

		private static bool _siFieldsReady;

		private static readonly Dictionary<object, object> _shopItemClones = new Dictionary<object, object>();

		private static Type _transactionType;

		private static MethodInfo _miTransactionLate;

		private static Camera _transactionCam;

		private static bool _trReentry;

		private static bool _trFieldsReady;

		private static FieldInfo _fTrFollow;

		private static FieldInfo _fTrAmount;

		private static FieldInfo _fTrStart;

		private static FieldInfo _fTrDestroySelf;

		private static FieldInfo _fTrText;

		private static readonly Dictionary<object, object> _transactionClones = new Dictionary<object, object>();

		private static Type _hazardMgrType;

		private static MethodInfo _miHazardLate;

		private static Camera _hazardCam;

		private static bool _hzReentry;

		private static bool _hzSwapped;

		private static NetworkIdentity _hzSavedLP;

		private static readonly Dictionary<object, object> _hazardClones = new Dictionary<object, object>();

		private static Type _shopHolderType;

		private static Type _shopPanelType;

		private static MethodInfo _miShopHolderEarly;

		private static FieldInfo _shopInstField;

		private static object _shopPanelOrig;

		private static object _shopPanelClone;

		private static FieldInfo _fShopContainer;

		private static FieldInfo _fShopShouldDisplay;

		private static FieldInfo _fShopCurrentData;

		private static FieldInfo _fShopNextData;

		private static FieldInfo _fShopIsVisible;

		private static FieldInfo _fShopIsTransitioning;

		private static FieldInfo _fShopHideOffset;

		private static FieldInfo _fShopAnimTime;

		private static FieldInfo _fShopEase;

		private static MethodInfo _miShopPanelUpdate;

		private static float _shopCloneProgress;

		private static object _easeObj;

		private static MethodInfo _miEaseEval;

		private static bool _easeStatic;

		private static bool _easeResolved;

		private static bool _shopHolderReentry;

		private static bool _shopPanelReady;

		private static bool _shopPanelFailed;

		private static FieldInfo _fInRotate;

		private static FieldInfo _fInPlace;

		private static FieldInfo _fInStartPickUp;

		private static FieldInfo _fInPickingUp;

		private static bool _stationFieldsReady;

		private static FieldInfo _fGrabData;

		private static FieldInfo _fGrabReq;

		private static FieldInfo _fRaised;

		private static ButtonControl _p2GrabBtn;

		private static ButtonControl _p2LiftBtn;

		private static ButtonControl _p2DriftBtn;

		private static bool _p2BtnsResolved;

		private static FieldInfo _fCamOffset;

		private static FieldInfo _fCamTransform;

		private static FieldInfo _fCamCamera;

		internal static bool SplitActive;

		private static Camera _p2Cam;

		private static Camera _mainCam;

		private static GameObject _p2CamGo;

		private static RenderTexture _mainOrigRT;

		private static bool _mainRTCaptured;

		private static Type _nitroCtrlType;

		private static Type _nitroBarType;

		private static FieldInfo _fNitroBars;

		private static FieldInfo _fNitroCharges;

		private static FieldInfo _fNitroActive;

		private static FieldInfo _fNitroBurn;

		private static FieldInfo _fNitroBuild;

		private static MethodInfo _miChargeCount;

		private static MethodInfo _miSetFull;

		private static MethodInfo _miSetEmpty;

		private static MethodInfo _miSetFill;

		private static object _nitroUI;

		private static Array _p1Bars;

		private static Array _p2Bars;

		private static bool _nitroReady;

		private static bool _nitroFailed;

		private static readonly Dictionary<object, NetworkIdentity> _stressBarOwner = new Dictionary<object, NetworkIdentity>();

		private static NetworkIdentity _sbSaved;

		private static bool _sbSwapped;

		private static bool _p1Restricted;

		private static Type _colorNetType;

		private static MethodInfo _miSetColorIdx;

		private static FieldInfo _fColorIdx;

		private static FieldInfo _fColorMgrRef;

		private static FieldInfo _fPlayerColors;

		private static bool _colorResolved;

		private static int _couchColorIdx = -1;

		private static readonly Dictionary<object, NetworkIdentity> _colorNetOwner = new Dictionary<object, NetworkIdentity>();

		private static Type _shiftMgrTypeJ;

		private static FieldInfo _fShiftPhaseJ;

		private static bool _joinReflTried;

		private static bool _joinPrevPressed;

		internal static void PatchAll(Harmony h)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Expected O, but got Unknown
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Expected O, but got Unknown
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Expected O, but got Unknown
			//IL_0516: Unknown result type (might be due to invalid IL or missing references)
			//IL_0523: Expected O, but got Unknown
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a3: Expected O, but got Unknown
			//IL_0621: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Expected O, but got Unknown
			//IL_069d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06aa: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_011b: Expected O, but got Unknown
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(NetworkIdentity), "isLocalPlayer");
			if (methodInfo != null)
			{
				h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_IsLocalPlayer", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[couch] patched NetworkIdentity.get_isLocalPlayer (forces our couch bodies local).");
			}
			else
			{
				Plugin.Log.LogWarning((object)"[couch] NetworkIdentity.isLocalPlayer getter not found — PoC disabled.");
			}
			MethodInfo methodInfo2 = AccessTools.Method(AccessTools.TypeByName("GameMenuUI"), "OnUpdatePresentation", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				h.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("MenuOpen_Transpiler", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[couch] patched GameMenuUI.OnUpdatePresentation (pad-2 Start joins instead of opening the menu).");
			}
			MethodInfo methodInfo3 = AccessTools.Method(AccessTools.TypeByName("PlayerStressBarUI"), "OnUpdatePresentation", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				h.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_StressBar", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_StressBar", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[couch] patched PlayerStressBarUI.OnUpdatePresentation (each crashout bar reads its OWN player).");
			}
			MethodInfo methodInfo4 = AccessTools.Method(AccessTools.TypeByName("PlayerColorManagerNetwork"), "OnUpdatePresentationEarly", (Type[])null, (Type[])null);
			if (methodInfo4 != null)
			{
				h.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_ColorNetEarly", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"[couch] patched PlayerColorManagerNetwork.OnUpdatePresentationEarly (couch body keeps its own color).");
			}
			try
			{
				InputSystem.onDeviceChange += OnDeviceChange;
				Plugin.Log.LogInfo((object)"[couch] watching device changes (late-connected gamepads get reset + quarantined from P1).");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[couch] onDeviceChange hook failed: " + ex.Message));
			}
			try
			{
				MethodInfo methodInfo5 = AccessTools.Method(AccessTools.TypeByName("NetworkUtil"), "ServerGetPing", (Type[])null, (Type[])null);
				if (methodInfo5 != null)
				{
					h.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_ServerGetPing", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[couch] patched NetworkUtil.ServerGetPing (null-conn guard).");
				}
				else
				{
					Plugin.Log.LogWarning((object)"[couch] NetworkUtil.ServerGetPing not found — null-conn guard skipped.");
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[couch] ServerGetPing guard failed to apply: " + ex2.Message));
			}
			try
			{
				_vehicleType = AccessTools.TypeByName("VehicleController");
				HarmonyMethod val = new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_VehSim", BindingFlags.Static | BindingFlags.NonPublic));
				HarmonyMethod val2 = new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_VehSim", BindingFlags.Static | BindingFlags.NonPublic));
				string[] array = new string[4] { "OnUpdatePresentation", "OnUpdateSimulationEarly", "OnUpdateSimulation", "OnUpdateSimulationLate" };
				foreach (string text in array)
				{
					MethodInfo methodInfo6 = AccessTools.Method(_vehicleType, text, (Type[])null, (Type[])null);
					if (methodInfo6 != null)
					{
						h.Patch((MethodBase)methodInfo6, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
				Plugin.Log.LogInfo((object)"[demux] patched VehicleController (per-body raw input).");
				HarmonyMethod val3 = new HarmonyMethod(typeof(CouchCoop).GetMethod("Driving_Transpiler", BindingFlags.Static | BindingFlags.NonPublic));
				array = new string[5] { "GetSteeringInput", "GetAccelerationInput", "GetBrakeInput", "GetDriftInput", "CheckForDrifting" };
				foreach (string text2 in array)
				{
					MethodInfo methodInfo7 = AccessTools.Method(_vehicleType, text2, (Type[])null, (Type[])null);
					if (methodInfo7 != null)
					{
						h.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
				Plugin.Log.LogInfo((object)"[demux] transpiled steering/accel/brake/drift getters + CheckForDrifting (P2 = game math).");
			}
			catch (Exception ex3)
			{
				Plugin.Log.LogWarning((object)("[demux] swap patch failed to apply: " + ex3.Message));
			}
			try
			{
				MethodInfo methodInfo8 = AccessTools.Method(AccessTools.TypeByName("PlayerGrabber"), "OnUpdatePresentation", (Type[])null, (Type[])null);
				if (methodInfo8 != null)
				{
					h.Patch((MethodBase)methodInfo8, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_GrabberInput", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[grab] patched PlayerGrabber.OnUpdatePresentation (P2 grab/lift).");
				}
			}
			catch (Exception ex4)
			{
				Plugin.Log.LogWarning((object)("[grab] patch failed: " + ex4.Message));
			}
			try
			{
				MethodInfo methodInfo9 = AccessTools.Method(AccessTools.TypeByName("CameraController"), "OnUpdatePresentation", (Type[])null, (Type[])null);
				if (methodInfo9 != null)
				{
					h.Patch((MethodBase)methodInfo9, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_CamFrame", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[cam] patched CameraController.OnUpdatePresentation (frame-both).");
				}
			}
			catch (Exception ex5)
			{
				Plugin.Log.LogWarning((object)("[cam] frame-both patch failed: " + ex5.Message));
			}
			try
			{
				MethodInfo methodInfo10 = AccessTools.Method(AccessTools.TypeByName("NitroController"), "OnUpdatePresentation", (Type[])null, (Type[])null);
				if (methodInfo10 != null)
				{
					h.Patch((MethodBase)methodInfo10, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_NitroPresentation", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[boost] patched NitroController.OnUpdatePresentation (per-player Gas->boost).");
				}
			}
			catch (Exception ex6)
			{
				Plugin.Log.LogWarning((object)("[boost] patch failed: " + ex6.Message));
			}
			_harmony = h;
			try
			{
				MethodInfo methodInfo11 = AccessTools.Method(AccessTools.TypeByName("CameraRenderTextureRenderPass"), "Execute", (Type[])null, (Type[])null);
				if (methodInfo11 != null)
				{
					h.Patch((MethodBase)methodInfo11, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_BlitPass", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[split] patched CameraRenderTextureRenderPass.Execute (skip fullscreen blit while split).");
				}
				else
				{
					Plugin.Log.LogWarning((object)"[split] CameraRenderTextureRenderPass.Execute not found — splitscreen disabled.");
				}
			}
			catch (Exception ex7)
			{
				Plugin.Log.LogWarning((object)("[split] blit-skip patch failed: " + ex7.Message));
			}
			try
			{
				MethodInfo methodInfo12 = AccessTools.Method(AccessTools.TypeByName("NitroUI"), "OnUpdatePresentation", (Type[])null, (Type[])null);
				if (methodInfo12 != null)
				{
					h.Patch((MethodBase)methodInfo12, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_NitroUI", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[hud] patched NitroUI.OnUpdatePresentation (per-player gauges while split).");
				}
			}
			catch (Exception ex8)
			{
				Plugin.Log.LogWarning((object)("[hud] NitroUI patch failed: " + ex8.Message));
			}
			try
			{
				MethodInfo methodInfo13 = AccessTools.Method(AccessTools.TypeByName("GameUtil"), "ServerTeleportPlayers", (Type[])null, (Type[])null);
				if (methodInfo13 != null)
				{
					h.Patch((MethodBase)methodInfo13, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_TeleportPlayers", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)"[transition] patched GameUtil.ServerTeleportPlayers (bring couch body along).");
				}
				else
				{
					Plugin.Log.LogWarning((object)"[transition] GameUtil.ServerTeleportPlayers not found — couch body may be left behind on transition.");
				}
			}
			catch (Exception ex9)
			{
				Plugin.Log.LogWarning((object)("[transition] patch failed: " + ex9.Message));
			}
		}

		private static void Post_TeleportPlayers()
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Plugin.FixTransition.Value)
				{
					CouchBodies.RemoveWhere((NetworkIdentity b) => (Object)(object)b == (Object)null);
					if (CouchBodies.Count != 0)
					{
						NetworkIdentity realHost = GetRealHost();
						Plugin.Log.LogInfo((object)("[transition] detected; anchoring couch body to real P1 netId=" + (((Object)(object)realHost != (Object)null) ? realHost.netId.ToString() : "<none>") + " @ " + (((Object)(object)realHost != (Object)null) ? ((object)HostPos(realHost)/*cast due to .constrained prefix*/).ToString() : "<null>") + "."));
						_reapplyLeft = 15;
						SnapCouchToHost(realHost, "transition");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[transition] flag failed: " + ex.Message));
			}
		}

		private static NetworkIdentity GetRealHost()
		{
			foreach (KeyValuePair<int, NetworkConnectionToClient> connection in NetworkServer.connections)
			{
				NetworkIdentity val = ((connection.Value != null) ? ((NetworkConnection)connection.Value).identity : null);
				if ((Object)(object)val != (Object)null && !CouchBodies.Contains(val))
				{
					return val;
				}
			}
			return null;
		}

		private static Vector3 HostPos(NetworkIdentity id)
		{
			//IL_0009: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)id == (Object)null)
			{
				return Vector3.zero;
			}
			Rigidbody componentInChildren = ((Component)id).GetComponentInChildren<Rigidbody>();
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				return ((Component)id).transform.position;
			}
			return componentInChildren.position;
		}

		private static void TickTransitionHold()
		{
			if (_reapplyLeft <= 0)
			{
				return;
			}
			_reapplyLeft--;
			try
			{
				SnapCouchToHost(GetRealHost(), (_reapplyLeft == 0) ? "reapply-final" : null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[transition] reapply failed: " + ex.Message));
				_reapplyLeft = 0;
			}
		}

		private unsafe static void SnapCouchToHost(NetworkIdentity host, string logWhy)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)host == (Object)null)
			{
				if (logWhy != null)
				{
					Plugin.Log.LogWarning((object)"[transition] no real P1 to anchor to.");
				}
				return;
			}
			Vector3 val = HostPos(host);
			Quaternion rotation = ((Component)host).transform.rotation;
			if (_entityType == null)
			{
				_entityType = AccessTools.TypeByName("Aggro.Core.Entity") ?? AccessTools.TypeByName("Entity");
				if (_entityType != null)
				{
					_miGetNetTransform = AccessTools.Method(_entityType, "get_netTransform", (Type[])null, (Type[])null);
				}
			}
			int num = 0;
			foreach (NetworkIdentity couchBody in CouchBodies)
			{
				if ((Object)(object)couchBody == (Object)null)
				{
					continue;
				}
				num++;
				Vector3 val2 = val + rotation * new Vector3(Plugin.TransitionSpacing.Value * (float)num, 0f, 0f);
				NetworkTransformBase val3 = null;
				if (_entityType != null && _miGetNetTransform != null)
				{
					Component component = ((Component)couchBody).GetComponent(_entityType);
					if ((Object)(object)component != (Object)null)
					{
						object? obj = _miGetNetTransform.Invoke(component, null);
						val3 = (NetworkTransformBase)((obj is NetworkTransformBase) ? obj : null);
					}
				}
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)couchBody).GetComponentInChildren<NetworkTransformBase>(true);
				}
				if ((Object)(object)val3 != (Object)null)
				{
					val3.ServerTeleport(val2, rotation);
				}
				Rigidbody componentInChildren = ((Component)couchBody).GetComponentInChildren<Rigidbody>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.position = val2;
					componentInChildren.rotation = rotation;
					componentInChildren.velocity = Vector3.zero;
					componentInChildren.angularVelocity = Vector3.zero;
				}
				if (logWhy != null)
				{
					ManualLogSource log = Plugin.Log;
					string[] obj2 = new string[7]
					{
						"[transition] snapped couch body netId=",
						couchBody.netId.ToString(),
						" to P1 @ ",
						null,
						null,
						null,
						null
					};
					Vector3 val4 = val2;
					obj2[3] = ((object)(*(Vector3*)(&val4))/*cast due to .constrained prefix*/).ToString();
					obj2[4] = " (";
					obj2[5] = logWhy;
					obj2[6] = ").";
					log.LogInfo((object)string.Concat(obj2));
				}
			}
		}

		private static void Post_NitroPresentation(object __instance)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (CouchBodies.Count == 0)
				{
					return;
				}
				Component val = (Component)((__instance is Component) ? __instance : null);
				NetworkIdentity val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInParent<NetworkIdentity>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				bool flag = CouchBodies.Contains(val2);
				bool flag2 = val2 == GetRealHost();
				if (!flag && !flag2)
				{
					return;
				}
				if (_fNitroInput == null)
				{
					_fNitroInput = AccessTools.Field(__instance.GetType(), "_nitroInput");
				}
				if (_fNitroInput == null)
				{
					return;
				}
				ReadOnlyArray<Gamepad> all = Gamepad.all;
				bool flag3;
				if (flag)
				{
					flag3 = false;
					if (!CouchMenu.IsOpen && all.Count >= 2)
					{
						EnsureP2ActionButtons(all[1]);
						flag3 = _boostBtnCache != null && _boostBtnCache.isPressed;
					}
				}
				else
				{
					flag3 = (Keyboard.current != null && ((ButtonControl)Keyboard.current.spaceKey).isPressed) || (all.Count >= 1 && all[0].buttonSouth != null && all[0].buttonSouth.isPressed);
				}
				_fNitroInput.SetValue(__instance, flag3);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[boost] " + ex.Message));
			}
		}

		private static void Post_IsLocalPlayer(NetworkIdentity __instance, ref bool __result)
		{
			if (!((CouchBodies.Count == 0) | __result) && CouchBodies.Contains(__instance))
			{
				__result = true;
			}
		}

		private static bool Pre_ServerGetPing(NetworkConnectionToClient conn, ref double __result)
		{
			if (conn != null)
			{
				return true;
			}
			__result = 0.0;
			return false;
		}

		private static void EnsureDemux()
		{
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: 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_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_011e: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			if (_demuxReady || _demuxFailed || !Plugin.DemuxInput.Value)
			{
				return;
			}
			try
			{
				if (_vehicleType == null)
				{
					_vehicleType = AccessTools.TypeByName("VehicleController");
				}
				Type type = AccessTools.TypeByName("AggroInput");
				_vehInputField = AccessTools.Field(AccessTools.TypeByName("AggroInputManager"), "input");
				_aggroAssetProp = AccessTools.Property(type, "asset");
				if (_vehInputField == null || _aggroAssetProp == null || !_vehInputField.IsStatic)
				{
					_demuxFailed = true;
					Plugin.Log.LogWarning((object)"[demux] AggroInputManager.input (static) or AggroInput.asset not found.");
					return;
				}
				ReadOnlyArray<Gamepad> all = Gamepad.all;
				if (all.Count < 2)
				{
					Plugin.Log.LogWarning((object)("[demux] need >=2 gamepads, have " + all.Count + " — couch body will mirror P1 until a 2nd pad is connected."));
					return;
				}
				Gamepad val = all[1];
				_p2Input = Activator.CreateInstance(type);
				InputActionAsset val2 = (InputActionAsset)_aggroAssetProp.GetValue(_p2Input);
				val2.devices = new ReadOnlyArray<InputDevice>((InputDevice[])(object)new InputDevice[1] { (InputDevice)val });
				val2.FindActionMap("Game", true).Enable();
				try
				{
					InputUser val3 = InputUser.PerformPairingWithDevice((InputDevice)(object)val, default(InputUser), (InputUserPairingOptions)0);
					((InputUser)(ref val3)).AssociateActionsWithUser((IInputActionCollection)(object)val2);
					Plugin.Log.LogInfo((object)("[demux] InputUser paired gamepad#2 -> P2 input (valid=" + ((InputUser)(ref val3)).valid + ")."));
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[demux] InputUser pairing failed: " + ex.Message));
				}
				object value = _vehInputField.GetValue(null);
				if (value != null)
				{
					InputActionAsset val4 = (InputActionAsset)_aggroAssetProp.GetValue(value);
					List<InputDevice> list = new List<InputDevice>();
					if (Keyboard.current != null)
					{
						list.Add((InputDevice)(object)Keyboard.current);
					}
					if (Mouse.current != null)
					{
						list.Add((InputDevice)(object)Mouse.current);
					}
					Enumerator<Gamepad> enumerator = all.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							Gamepad current = enumerator.Current;
							if (current != val)
							{
								list.Add((InputDevice)(object)current);
							}
						}
					}
					finally
					{
						((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
					}
					val4.devices = new ReadOnlyArray<InputDevice>(list.ToArray());
				}
				DumpGameBindings(val2);
				_demuxReady = true;
				Plugin.Log.LogInfo((object)("[demux] ready: gamepad#2 '" + ((InputControl)val).displayName + "' -> couch body; P1 input excludes it."));
				Plugin.Log.LogInfo((object)("[demux] P2 input devices = " + DevList(val2) + "   (should be ONLY gamepad#2)"));
				object value2 = _vehInputField.GetValue(null);
				if (value2 != null)
				{
					Plugin.Log.LogInfo((object)("[demux] P1 input devices = " + DevList((InputActionAsset)_aggroAssetProp.GetValue(value2)) + "   (should EXCLUDE gamepad#2)"));
				}
			}
			catch (Exception ex2)
			{
				_demuxFailed = true;
				Plugin.Log.LogError((object)("[demux] setup failed (driving will mirror P1): " + ex2));
			}
		}

		private static void DumpGameBindings(InputActionAsset asset)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InputActionMap val = asset.FindActionMap("Game", false);
				if (val == null)
				{
					Plugin.Log.LogWarning((object)"[bind] Game map not found.");
					return;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[bind] Game action map bindings:");
				Enumerator<InputAction> enumerator = val.actions.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InputAction current = enumerator.Current;
						List<string> list = new List<string>();
						Enumerator<InputBinding> enumerator2 = current.bindings.GetEnumerator();
						try
						{
							while (enumerator2.MoveNext())
							{
								InputBinding current2 = enumerator2.Current;
								if (!string.IsNullOrEmpty(((InputBinding)(ref current2)).effectivePath))
								{
									list.Add(((InputBinding)(ref current2)).effectivePath);
								}
							}
						}
						finally
						{
							((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
						}
						stringBuilder.AppendLine("  '" + current.name + "' (" + ((object)current.type/*cast due to .constrained prefix*/).ToString() + ") -> " + string.Join(" | ", list.ToArray()));
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				Plugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[bind] dump failed: " + ex.Message));
			}
		}

		private static string DevList(InputActionAsset a)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			ReadOnlyArray<InputDevice>? devices = a.devices;
			if (!devices.HasValue)
			{
				return "<null = ALL devices (filter NOT applied!)>";
			}
			StringBuilder stringBuilder = new StringBuilder();
			Enumerator<InputDevice> enumerator = devices.Value.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputDevice current = enumerator.Current;
					stringBuilder.Append("'" + ((InputControl)current).displayName + "' ");
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			if (devices.Value.Count != 0)
			{
				return stringBuilder.ToString();
			}
			return "<empty>";
		}

		private static void Pre_VehSim(object __instance, out object __state)
		{
			__state = null;
			if (_demuxReady && _p2Input != null && CouchBodies.Count != 0 && !(_vehInputField == null))
			{
				Component val = (Component)((__instance is Component) ? __instance : null);
				NetworkIdentity val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<NetworkIdentity>() : null);
				if ((Object)(object)val2 != (Object)null && CouchBodies.Contains(val2))
				{
					__state = _vehInputField.GetValue(null);
					_vehInputField.SetValue(null, _p2Input);
				}
			}
		}

		private static void Post_VehSim(object __state)
		{
			if (__state != null)
			{
				_vehInputField.SetValue(null, __state);
			}
		}

		private static IEnumerable<CodeInstruction> Driving_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(CouchCoop), "SteeringFor", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(CouchCoop), "BrakeFor", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(CouchCoop), "DriftFor", (Type[])null, (Type[])null);
			for (int i = 0; i < list.Count; i++)
			{
				MethodInfo methodInfo4 = list[i].operand as MethodInfo;
				if (methodInfo4 == null)
				{
					continue;
				}
				MethodInfo methodInfo5 = ((methodInfo4.Name == "get_Steering") ? methodInfo : ((methodInfo4.Name == "get_Brake") ? methodInfo2 : ((methodInfo4.Name == "get_Drift") ? methodInfo3 : null)));
				if (methodInfo5 == null)
				{
					continue;
				}
				for (int j = i + 1; j < list.Count && j <= i + 4; j++)
				{
					MethodInfo methodInfo6 = list[j].operand as MethodInfo;
					if (methodInfo6 != null && methodInfo6.Name == "ReadValue")
					{
						list.Insert(j + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
						list.Insert(j + 2, new CodeInstruction(OpCodes.Call, (object)methodInfo5));
						i = j + 2;
						break;
					}
				}
			}
			return list;
		}

		private static Vector2 SteeringFor(Vector2 orig, object veh)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (CouchBodies.Count == 0)
				{
					return orig;
				}
				Component val = (Component)((veh is Component) ? veh : null);
				NetworkIdentity val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<NetworkIdentity>() : null);
				if ((Object)(object)val2 != (Object)null && CouchBodies.Contains(val2))
				{
					if (CouchMenu.IsOpen)
					{
						return Vector2.zero;
					}
					ReadOnlyArray<Gamepad> all = Gamepad.all;
					if (all.Count >= 2 && all[1].leftStick != null)
					{
						return ((InputControl<Vector2>)(object)all[1].leftStick).ReadValue();
					}
				}
				return orig;
			}
			catch
			{
				return orig;
			}
		}

		private static float BrakeFor(float orig, object veh)
		{
			//IL_0052: 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)
			try
			{
				if (CouchBodies.Count == 0)
				{
					return orig;
				}
				Component val = (Component)((veh is Component) ? veh : null);
				NetworkIdentity val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<NetworkIdentity>() : null);
				if ((Object)(object)val2 != (Object)null && CouchBodies.Contains(val2))
				{
					if (CouchMenu.IsOpen)
					{
						return 0f;
					}
					ReadOnlyArray<Gamepad> all = Gamepad.all;
					if (all.Count < 2)
					{
						return 0f;
					}
					EnsureP2ActionButtons(all[1]);
					return (_brakeBtnCache != null) ? ((InputControl<float>)(object)_brakeBtnCache).ReadValue() : 0f;
				}
				return orig;
			}
			catch
			{
				return orig;
			}
		}

		private static float DriftFor(float orig, object veh)
		{
			//IL_0052: 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)
			try
			{
				if (CouchBodies.Count == 0)
				{
					return orig;
				}
				Component val = (Component)((veh is Component) ? veh : null);
				NetworkIdentity val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<NetworkIdentity>() : null);
				if ((Object)(object)val2 != (Object)null && CouchBodies.Contains(val2))
				{
					if (CouchMenu.IsOpen)
					{
						return 0f;
					}
					ReadOnlyArray<Gamepad> all = Gamepad.all;
					if (all.Count < 2)
					{
						return 0f;
					}
					EnsureP2ActionButtons(all[1]);
					return (_driftBtnCache != null) ? ((InputControl<float>)(object)_driftBtnCache).ReadValue() : 0f;
				}
				return orig;
			}
			catch
			{
				return orig;
			}
		}

		private static void EnsureActionPatches()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Expected O, but got Unknown
			//IL_0247: Expected O, but got Unknown
			//IL_0247: Expected O, but got Unknown
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_02b6: Expected O, but got Unknown
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Expected O, but got Unknown
			//IL_0353: Expected O, but got Unknown
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Expected O, but got Unknown
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0538: Unknown result type (might be due to invalid IL or missing references)
			//IL_0544: Expected O, but got Unknown
			//IL_0544: Expected O, but got Unknown
			//IL_0544: Expected O, but got Unknown
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Expected O, but got Unknown
			//IL_0456: Expected O, but got Unknown
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Expected O, but got Unknown
			//IL_06bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fd: Expected O, but got Unknown
			//IL_06fd: Expected O, but got Unknown
			//IL_06fd: Expected O, but got Unknown
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0602: Unknown result type (might be due to invalid IL or missing references)
			//IL_060f: Expected O, but got Unknown
			//IL_060f: Expected O, but got Unknown
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			//IL_063b: Expected O, but got Unknown
			if (_actionPatchesApplied || _harmony == null)
			{
				return;
			}
			_actionPatchesApplied = true;
			try
			{
				Type type = AccessTools.TypeByName("CCTags");
				if (type != null)
				{
					RuntimeHelpers.RunClassConstructor(type.TypeHandle);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[actions] CCTags pre-init failed: " + ex.Message));
			}
			try
			{
				HarmonyMethod val = new HarmonyMethod(typeof(CouchCoop).GetMethod("Tool_UseBox_Transpiler", BindingFlags.Static | BindingFlags.NonPublic));
				string[] array = new string[4] { "PlayerBlower", "PlayerExtinguisher", "PlayerVacuum", "PlayerScrubber" };
				for (int i = 0; i < array.Length; i++)
				{
					MethodInfo methodInfo = AccessTools.Method(AccessTools.TypeByName(array[i]), "OnUpdateSimulation", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
				MethodInfo methodInfo2 = AccessTools.Method(AccessTools.TypeByName("PlayerStationPlacer"), "OnUpdatePresentation", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_StationInput", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo3 = AccessTools.Method(AccessTools.TypeByName("PingController"), "OnUpdatePresentation", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					_harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Beep_Transpiler", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo4 = AccessTools.Method(AccessTools.TypeByName("Booststrip"), "OnUpdateSimulation", (Type[])null, (Type[])null);
				if (methodInfo4 != null)
				{
					_harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_Booststrip", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo5 = AccessTools.Method(AccessTools.TypeByName("HotkeyHintsUI"), "OnUpdatePresentationLate", (Type[])null, (Type[])null);
				if (methodInfo5 != null)
				{
					_harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_Hints", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_Hints", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(CouchCoop).GetMethod("Hints_CamTranspiler", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo6 = AccessTools.Method(AccessTools.TypeByName("FloaterManagerUI"), "UpdateFloaters", (Type[])null, (Type[])null);
				if (methodInfo6 != null)
				{
					_miUpdateFloaters = methodInfo6;
					_harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_Floaters", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(CouchCoop).GetMethod("Floater_CamTranspiler", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null);
				}
				_shopHolderType = AccessTools.TypeByName("ShopHolder");
				_miShopHolderEarly = AccessTools.Method(_shopHolderType, "OnUpdatePresentationEarly", (Type[])null, (Type[])null);
				_shopPanelType = AccessTools.TypeByName("ShopPanelUI");
				if (_miShopHolderEarly != null && _shopPanelType != null)
				{
					_harmony.Patch((MethodBase)_miShopHolderEarly, new HarmonyMethod(typeof(CouchCoop).GetMethod("Pre_ShopHolder", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_ShopHolder", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					MethodInfo methodInfo7 = AccessTools.Method(_shopPanelType, "OnUpdatePresentation", (Type[])null, (Type[])null);
					if (methodInfo7 != null)
					{
						_harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchCoop).GetMethod("Post_ShopPanelTick", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (