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 TMPro; using UnityEngine; using UnityEngine.Events; 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("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0")] [assembly: AssemblyProduct("CouchCrew")] [assembly: AssemblyTitle("CouchCrew")] [assembly: AssemblyVersion("1.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 { internal static class CouchControllerMenu { private static Type _aggroSettingsType; private static Type _settingBaseType; private static Type _dropdownSettingType; private static Type _optionsType; private static Type _ddUiType; private static MethodInfo _miAddSetting; private static ConstructorInfo _ddCtor; private static Type _ddCallbackType; private static FieldInfo _fDdDropdown; private static FieldInfo _fDdSetting; private static bool _ready; private static object _twoPlayerSetting; private static object _p1Setting; private static object _p2Setting; private static readonly string[] _twoPlayerLabels = new string[2] { "Off", "On" }; private static readonly List _p1Labels = new List(); private static readonly List _p1Keys = new List(); private static readonly List _p2Labels = new List(); private static readonly List _p2Keys = new List(); internal static void PatchAll(Harmony h) { //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Expected O, but got Unknown //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Expected O, but got Unknown //IL_02fd: Expected O, but got Unknown try { _aggroSettingsType = AccessTools.TypeByName("Aggro.Core.AggroSettings"); _settingBaseType = AccessTools.TypeByName("Aggro.Core.AggroSettingBase"); _dropdownSettingType = AccessTools.TypeByName("Aggro.Core.DropdownSetting"); _optionsType = AccessTools.TypeByName("Options"); _ddUiType = AccessTools.TypeByName("Aggro.Core.DropdownSettingUI"); if (_aggroSettingsType != null && _settingBaseType != null) { _miAddSetting = AccessTools.Method(_aggroSettingsType, "AddSetting", new Type[4] { typeof(string), typeof(string), typeof(string), _settingBaseType }, (Type[])null); } if (_dropdownSettingType != null) { ConstructorInfo[] constructors = _dropdownSettingType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (ConstructorInfo constructorInfo in constructors) { ParameterInfo[] parameters = constructorInfo.GetParameters(); if (parameters.Length == 3 && parameters[0].ParameterType == typeof(int) && parameters[1].ParameterType == typeof(string[])) { _ddCtor = constructorInfo; _ddCallbackType = parameters[2].ParameterType; break; } } } if (_ddUiType != null) { _fDdDropdown = AccessTools.Field(_ddUiType, "dropdown"); _fDdSetting = AccessTools.Field(_ddUiType, "_setting"); } _ready = _miAddSetting != null && _ddCtor != null && _ddCallbackType != null && _optionsType != null; if (!_ready) { Plugin.Log.LogWarning((object)("[couch] controller-picker settings reflection incomplete — addSetting=" + (_miAddSetting != null) + " ddCtor=" + (_ddCtor != null) + " options=" + (_optionsType != null) + " ddUi=" + (_ddUiType != null) + ". Lobby controller rows disabled (use the P2 menu instead).")); } else { MethodInfo methodInfo = AccessTools.Method(_optionsType, "AddGameSettings", (Type[])null, (Type[])null); if (methodInfo != null) { h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CouchControllerMenu).GetMethod("Post_AddGameSettings", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Plugin.Log.LogWarning((object)"[couch] Options.AddGameSettings not found — lobby controller rows disabled."); } MethodInfo methodInfo2 = AccessTools.Method(_ddUiType, "Refresh", (Type[])null, (Type[])null); if (methodInfo2 != null) { h.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(CouchControllerMenu).GetMethod("Pre_DropdownRefresh", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(CouchControllerMenu).GetMethod("Post_DropdownRefresh", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[couch] controller-picker patch: " + ex)); } } private static void BuildOptions() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) _p1Labels.Clear(); _p1Keys.Clear(); _p2Labels.Clear(); _p2Keys.Clear(); _p1Labels.Add("Keyboard & Mouse"); _p1Keys.Add("keyboard"); Gamepad val = (Plugin.P1UsesKeyboard.Value ? null : CouchCoop.P1Pad); Gamepad p2Pad = CouchCoop.P2Pad; Enumerator enumerator = Gamepad.all.GetEnumerator(); try { while (enumerator.MoveNext()) { Gamepad current = enumerator.Current; string item = CouchCoop.DeviceLabel(current); if (current != p2Pad) { _p1Labels.Add(item); _p1Keys.Add(item); } if (current != val) { _p2Labels.Add(item); _p2Keys.Add(item); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } if (_p2Labels.Count == 0) { _p2Labels.Add("(no controller)"); _p2Keys.Add("auto"); } } private static int CurrentTwoPlayerIndex() { if (!Plugin.P1UsesKeyboard.Value) { return 0; } return 1; } private static void OnTwoPlayerSaved(int index) { try { bool flag = index == 1; Plugin.P1UsesKeyboard.Value = flag; if (flag) { Plugin.P1Device.Value = "auto"; } CouchCoop.ApplyDeviceSelection(); Plugin.Log.LogInfo((object)("[couch] 2 Player Mode " + (flag ? "ON (P1 on keyboard, controller freed for P2)" : "OFF"))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[couch] 2-player mode save: " + ex)); } } private static int CurrentP1Index() { if (Plugin.P1UsesKeyboard.Value) { return 0; } Gamepad p1Pad = CouchCoop.P1Pad; string item = ((p1Pad != null) ? CouchCoop.DeviceLabel(p1Pad) : Plugin.P1Device.Value); int num = _p1Keys.IndexOf(item); if (num < 0) { return 0; } return num; } private static int CurrentP2Index() { Gamepad p2Pad = CouchCoop.P2Pad; string item = ((p2Pad != null) ? CouchCoop.DeviceLabel(p2Pad) : Plugin.P2Device.Value); int num = _p2Keys.IndexOf(item); if (num < 0) { return 0; } return num; } private static void Post_AddGameSettings() { try { if (_ready) { BuildOptions(); Delegate obj = Delegate.CreateDelegate(_ddCallbackType, typeof(CouchControllerMenu).GetMethod("OnTwoPlayerSaved", BindingFlags.Static | BindingFlags.NonPublic)); _twoPlayerSetting = _ddCtor.Invoke(new object[3] { CurrentTwoPlayerIndex(), (string[])_twoPlayerLabels.Clone(), obj }); _miAddSetting.Invoke(null, new object[4] { "couch-2player", "game", "", _twoPlayerSetting }); Delegate obj2 = Delegate.CreateDelegate(_ddCallbackType, typeof(CouchControllerMenu).GetMethod("OnP1Saved", BindingFlags.Static | BindingFlags.NonPublic)); _p1Setting = _ddCtor.Invoke(new object[3] { CurrentP1Index(), _p1Labels.ToArray(), obj2 }); _miAddSetting.Invoke(null, new object[4] { "couch-p1-device", "game", "", _p1Setting }); Delegate obj3 = Delegate.CreateDelegate(_ddCallbackType, typeof(CouchControllerMenu).GetMethod("OnP2Saved", BindingFlags.Static | BindingFlags.NonPublic)); _p2Setting = _ddCtor.Invoke(new object[3] { CurrentP2Index(), _p2Labels.ToArray(), obj3 }); _miAddSetting.Invoke(null, new object[4] { "couch-p2-device", "game", "", _p2Setting }); Plugin.Log.LogInfo((object)("[couch] registered P1/P2 Controller dropdowns (" + string.Join(", ", _p1Labels.ToArray()) + ").")); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[couch] controller rows register: " + ex)); } } private static void OnP1Saved(int index) { try { if (index >= 0 && index < _p1Keys.Count) { if (index == 0) { Plugin.P1UsesKeyboard.Value = true; Plugin.P1Device.Value = "auto"; } else { Plugin.P1UsesKeyboard.Value = false; Plugin.P1Device.Value = _p1Keys[index]; } if (!Plugin.P1UsesKeyboard.Value && CouchCoop.P1Pad != null && CouchCoop.P1Pad == CouchCoop.P2Pad) { Plugin.P2Device.Value = "auto"; } CouchCoop.ApplyDeviceSelection(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[couch] P1 device save: " + ex)); } } private static void OnP2Saved(int index) { try { if (index >= 0 && index < _p2Keys.Count) { Plugin.P2Device.Value = _p2Keys[index]; if (!Plugin.P1UsesKeyboard.Value && CouchCoop.P2Pad != null && CouchCoop.P2Pad == CouchCoop.P1Pad) { Plugin.P1Device.Value = "auto"; } CouchCoop.ApplyDeviceSelection(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[couch] P2 device save: " + ex)); } } private static bool Pre_DropdownRefresh(object __instance) { try { if (_fDdSetting == null) { return true; } object value = _fDdSetting.GetValue(__instance); if ((_p1Setting != null && value == _p1Setting) || (_p2Setting != null && value == _p2Setting) || (_twoPlayerSetting != null && value == _twoPlayerSetting)) { return false; } } catch { } return true; } private static void Post_DropdownRefresh(object __instance) { try { if (_fDdSetting == null) { return; } object value = _fDdSetting.GetValue(__instance); bool flag = _twoPlayerSetting != null && value == _twoPlayerSetting; bool flag2 = _p1Setting != null && value == _p1Setting; bool flag3 = _p2Setting != null && value == _p2Setting; if (!flag2 && !flag3 && !flag) { return; } TMP_Text[] componentsInChildren; if (flag) { TMP_Dropdown val = (TMP_Dropdown)((_fDdDropdown != null) ? /*isinst with value type is only supported in some contexts*/: null); int num = CurrentTwoPlayerIndex(); if ((Object)(object)val != (Object)null) { val.ClearOptions(); val.AddOptions(new List(_twoPlayerLabels)); if (num >= 0 && num < _twoPlayerLabels.Length) { val.SetValueWithoutNotify(num); } if ((Object)(object)val.captionText != (Object)null && num >= 0 && num < _twoPlayerLabels.Length) { val.captionText.text = _twoPlayerLabels[num]; } } Component val2 = (Component)((__instance is Component) ? __instance : null); if (!((Object)(object)val2 != (Object)null)) { return; } componentsInChildren = val2.GetComponentsInChildren(true); foreach (TMP_Text val3 in componentsInChildren) { if (!((Object)(object)val != (Object)null) || !val3.transform.IsChildOf(((Component)val).transform)) { val3.text = "2 Player Mode"; break; } } return; } BuildOptions(); List list = (flag2 ? _p1Labels : _p2Labels); int num2 = (flag2 ? CurrentP1Index() : CurrentP2Index()); TMP_Dropdown val4 = (TMP_Dropdown)((_fDdDropdown != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val4 != (Object)null) { val4.ClearOptions(); val4.AddOptions(new List(list)); if (num2 >= 0 && num2 < list.Count) { val4.SetValueWithoutNotify(num2); } if ((Object)(object)val4.captionText != (Object)null && num2 >= 0 && num2 < list.Count) { val4.captionText.text = list[num2]; } } Component val5 = (Component)((__instance is Component) ? __instance : null); if (!((Object)(object)val5 != (Object)null)) { return; } componentsInChildren = val5.GetComponentsInChildren(true); foreach (TMP_Text val6 in componentsInChildren) { if (!((Object)(object)val4 != (Object)null) || !val6.transform.IsChildOf(((Component)val4).transform)) { val6.text = (flag2 ? "P1 Controller" : "P2 Controller"); break; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[couch] controller row refresh: " + ex)); } } } 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.renderMode = (RenderMode)0; _canvas.sortingOrder = 29500; _go.AddComponent().uiScaleMode = (ScaleMode)0; GameObject val = new GameObject("Image"); val.transform.SetParent(_go.transform, false); _raw = val.AddComponent(); _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 cfg; public Action action; } internal static bool IsOpen; private static Item[] _items; private static Item[] _mainItems; private static Item[] _controlsItems; private static int _maxRows; private static string _pageTitle = "PLAYER 2"; private static GameObject _go; private static GameObject _panel; private static object _title; private static object _msg; private static GameObject[] _rowGo; private static Image[] _rowBg; private static object[] _rowLabel; private static bool _ready; private static bool _failed; private static Type _tmpType; private static PropertyInfo _fontProp; private static object _font; private static int _sel; private static ConfigEntry _capTarget; private static string _capLabel; private static bool _prevUp; private static bool _prevDown; private static bool _prevA; private static bool _capWait; private static bool _harvested; private static Sprite _btnSprite; private static Sprite _panelSprite; private static Type _btnType = (Type)1; private static Type _panelType = (Type)1; private static Color _baseImgColor = new Color(0.16f, 0.16f, 0.2f, 0.96f); private static Color _cbNormal = Color.white; private static Color _cbHi = new Color(1f, 0.84f, 0.38f, 1f); private static Color _labelColor = Color.white; private static Color _panelColor = new Color(0f, 0f, 0f, 0.82f); private static float _harvestedFontSize = 0f; private const float W = 460f; private const float TitleH = 48f; private const float RowH = 38f; private const float TitleFont = 28f; private const float RowFont = 20f; private static bool _stateLogged; private static MethodInfo _miUiCam; private static bool _uiCamTried; private static void BuildItems() { if (_mainItems == null) { _controlsItems = new Item[9] { 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 = "‹ Back", action = delegate { GoToPage(_mainItems, "PLAYER 2"); } } }; _mainItems = new Item[4] { new Item { label = "Resume", action = Close }, new Item { label = "Change Color", action = CouchCoop.CycleCouchColor }, new Item { label = "Controls ›", action = delegate { GoToPage(_controlsItems, "CONTROLS"); } }, new Item { label = "Leave Game", action = delegate { Close(); CouchCoop.LeaveCouch(); } } }; _items = _mainItems; _maxRows = Math.Max(_mainItems.Length, _controlsItems.Length); } } private static void GoToPage(Item[] items, string title) { _items = items; _pageTitle = title; _sel = 0; _capTarget = null; _prevUp = (_prevDown = (_prevA = true)); ResizePanel(); Redraw(); } private static void ResizePanel() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_panel == (Object)null)) { int num = ((_items != null) ? _items.Length : _maxRows); RectTransform component = _panel.GetComponent(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(460f, 48f + (float)num * 38f + 22f); } } } internal static void HandleStartPress() { if (!IsOpen) { Open(); } else if (_capTarget != null) { _capTarget = null; Redraw(); } else if (_items != _mainItems) { GoToPage(_mainItems, "PLAYER 2"); } else { Close(); } } internal static void Open() { DestroyUi(); BuildItems(); _items = _mainItems; _pageTitle = "PLAYER 2"; if (EnsureUi()) { 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; _panel = null; _title = null; _msg = null; _rowGo = null; _rowBg = null; _rowLabel = null; _ready = false; } } private static void LogOpenState() { //IL_00b7: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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(); 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(" scaleFactor=") .Append(component.scaleFactor.ToString("0.00")); } StringBuilder stringBuilder2 = stringBuilder.Append(" rootLossy="); Vector3 lossyScale = _go.transform.lossyScale; stringBuilder2.Append(((Vector3)(ref lossyScale)).ToString("0.00")); if ((Object)(object)_panel != (Object)null) { StringBuilder stringBuilder3 = stringBuilder.Append(" panelLossy="); lossyScale = _panel.transform.lossyScale; stringBuilder3.Append(((Vector3)(ref lossyScale)).ToString("0.00")); } 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_0051: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return; } if (CouchCoop.CouchBodies.Count == 0) { Close(); return; } LogOpenState(); Gamepad p2Pad = CouchCoop.P2Pad; if (p2Pad == null) { Close(); return; } if (_capTarget != null) { TickCapture(p2Pad); return; } float num = ((p2Pad.leftStick != null) ? ((InputControl)(object)p2Pad.leftStick).ReadValue().y : 0f); bool flag = (p2Pad.dpad != null && p2Pad.dpad.up.isPressed) || num > 0.6f; bool flag2 = (p2Pad.dpad != null && p2Pad.dpad.down.isPressed) || num < -0.6f; bool flag3 = p2Pad.buttonSouth != null && p2Pad.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 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() { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0131: 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) if (_capTarget != null) { SetText(_title, _pageTitle); for (int i = 0; i < _rowGo.Length; i++) { _rowGo[i].SetActive(false); } if (_msg != null) { SetActiveObj(_msg, active: true); SetText(_msg, "Press a button on controller 2\nto use for\n\n" + _capLabel.ToUpperInvariant() + "\n\n(Start = cancel)"); } return; } SetText(_title, _pageTitle); if (_msg != null) { SetActiveObj(_msg, active: false); } for (int j = 0; j < _rowGo.Length; j++) { bool flag = j < _items.Length; _rowGo[j].SetActive(flag); if (flag) { bool flag2 = j == _sel; Item item = _items[j]; string text = item.label; if (item.cfg != null) { text = text + ": " + item.cfg.Value; } if (flag2) { text = "" + text + ""; } SetText(_rowLabel[j], text); if ((Object)(object)_rowBg[j] != (Object)null) { ((Graphic)_rowBg[j]).color = _baseImgColor * (flag2 ? _cbHi : _cbNormal); } } } } private static bool EnsureUi() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0219: 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_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_0307: 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"); if (_font == null) { 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; } } } } HarvestStyle(); _go = new GameObject("CouchCrew_P2Menu"); Object.DontDestroyOnLoad((Object)(object)_go); Canvas val2 = _go.AddComponent(); 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.32f) : new Vector2(0.75f, 0.5f)); int maxRows = _maxRows; float num = 48f + (float)maxRows * 38f + 22f; _panel = new GameObject("Panel"); _panel.transform.SetParent(_go.transform, false); Image val5 = _panel.AddComponent(); if ((Object)(object)_panelSprite != (Object)null) { val5.sprite = _panelSprite; val5.type = _panelType; } ((Graphic)val5).color = _panelColor; RectTransform component = _panel.GetComponent(); Vector2 val6 = (component.pivot = val4); Vector2 anchorMin = (component.anchorMax = val6); component.anchorMin = anchorMin; component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(460f, num); _title = MakeLabel(_panel.transform, "Title", stretch: false, new Vector2(0f, -6f), new Vector2(436f, 40f), _labelColor, 28f, "Center", wrap: false); _rowGo = (GameObject[])(object)new GameObject[maxRows]; _rowBg = (Image[])(object)new Image[maxRows]; _rowLabel = new object[maxRows]; for (int j = 0; j < maxRows; j++) { GameObject val9 = new GameObject("Row" + j); val9.transform.SetParent(_panel.transform, false); Image val10 = val9.AddComponent(); if ((Object)(object)_btnSprite != (Object)null) { val10.sprite = _btnSprite; val10.type = _btnType; } ((Graphic)val10).color = _baseImgColor * _cbNormal; RectTransform component2 = val9.GetComponent(); anchorMin = (component2.anchorMax = new Vector2(0.5f, 1f)); component2.anchorMin = anchorMin; component2.pivot = new Vector2(0.5f, 1f); component2.sizeDelta = new Vector2(434f, 33f); component2.anchoredPosition = new Vector2(0f, 0f - (48f + (float)j * 38f)); _rowGo[j] = val9; _rowBg[j] = val10; _rowLabel[j] = MakeLabel(val9.transform, "Label", stretch: true, Vector2.zero, Vector2.zero, _labelColor, 20f, "Left", wrap: false); } _msg = MakeLabel(_panel.transform, "Msg", stretch: false, new Vector2(0f, -62f), new Vector2(424f, (float)maxRows * 38f), _labelColor, 22f, "Center", wrap: true); SetActiveObj(_msg, active: false); ResizePanel(); SetLayerRecursive(_go.transform, 5); _go.SetActive(false); _ready = true; Plugin.Log.LogInfo((object)("[p2menu] created native-style (font=" + (_font != null) + ", harvested=" + _harvested + ", harvestedFontSize=" + _harvestedFontSize.ToString("0.0") + ", 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 unsafe static void HarvestStyle() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_0289: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) if (_harvested) { return; } try { Type type = AccessTools.TypeByName("GameMenuUI"); if (type == null) { Plugin.Log.LogInfo((object)"[p2menu] style harvest: GameMenuUI type not found."); return; } Button val = null; Object val2 = null; Object[] array = Resources.FindObjectsOfTypeAll(type); foreach (Object val3 in array) { Component val4 = (Component)(object)((val3 is Component) ? val3 : null); if (!((Object)(object)val4 == (Object)null)) { Button val5 = FindMenuButton(type, val4); if ((Object)(object)val5 != (Object)null) { val = val5; val2 = val3; break; } } } if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)"[p2menu] style harvest: no live GameMenuUI button yet (will retry next open)."); return; } Image val6 = (Image)(((Object)(object)((Selectable)val).image != (Object)null) ? ((object)((Selectable)val).image) : ((object)/*isinst with value type is only supported in some contexts*/)); if ((Object)(object)val6 != (Object)null) { _btnSprite = val6.sprite; _btnType = val6.type; _baseImgColor = ((Graphic)val6).color; } ColorBlock colors = ((Selectable)val).colors; _cbNormal = ((ColorBlock)(ref colors)).normalColor; _cbHi = ((ColorBlock)(ref colors)).highlightedColor; if (_tmpType != null) { Component componentInChildren = ((Component)val).GetComponentInChildren(_tmpType, true); if ((Object)(object)componentInChildren != (Object)null) { if (_fontProp != null) { object value = _fontProp.GetValue(componentInChildren); if (value != null) { _font = value; } } if (GetProp(componentInChildren, "fontSize") is float num && num > 1f) { _harvestedFontSize = num; } if (GetProp(componentInChildren, "color") is Color labelColor) { _labelColor = labelColor; } } } FieldInfo fieldInfo = AccessTools.Field(type, "container"); if (fieldInfo != null && val2 != (Object)null) { object? value2 = fieldInfo.GetValue(val2); Transform val7 = (Transform)((value2 is Transform) ? value2 : null); if ((Object)(object)val7 != (Object)null) { Image component = ((Component)val7).GetComponent(); if ((Object)(object)component == (Object)null && (Object)(object)val7.parent != (Object)null) { component = ((Component)val7.parent).GetComponent(); } if ((Object)(object)component != (Object)null) { _panelSprite = component.sprite; _panelType = component.type; } } } _harvested = true; ManualLogSource log = Plugin.Log; string[] obj = new string[15] { "[p2menu] style harvested: btnSprite=", ((Object)(object)_btnSprite != (Object)null) ? ((Object)_btnSprite).name : "null", " baseCol=", null, null, null, null, null, null, null, null, null, null, null, null }; Color baseImgColor = _baseImgColor; obj[3] = ((object)(*(Color*)(&baseImgColor))/*cast due to .constrained prefix*/).ToString(); obj[4] = " normal="; baseImgColor = _cbNormal; obj[5] = ((object)(*(Color*)(&baseImgColor))/*cast due to .constrained prefix*/).ToString(); obj[6] = " hi="; baseImgColor = _cbHi; obj[7] = ((object)(*(Color*)(&baseImgColor))/*cast due to .constrained prefix*/).ToString(); obj[8] = " font="; obj[9] = (_font != null).ToString(); obj[10] = " gameFontSize="; obj[11] = _harvestedFontSize.ToString("0.0"); obj[12] = " panelSprite="; obj[13] = (((Object)(object)_panelSprite != (Object)null) ? ((Object)_panelSprite).name : "null"); obj[14] = "."; log.LogInfo((object)string.Concat(obj)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[p2menu] harvest: " + ex.Message)); } } private static Button FindMenuButton(Type gmType, Component gm) { try { FieldInfo fieldInfo = AccessTools.Field(gmType, "container"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(gm); Transform val = (Transform)((value is Transform) ? value : null); if ((Object)(object)val != (Object)null) { Button[] componentsInChildren = ((Component)val).GetComponentsInChildren