Decompiled source of BonkCoop v0.2.3

BonkCoop.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Actors.Enemies;
using Assets.Scripts.Actors;
using Assets.Scripts.Actors.Enemies;
using Assets.Scripts.Actors.Player;
using Assets.Scripts.Camera;
using Assets.Scripts.Game.Other;
using Assets.Scripts.Inventory__Items__Pickups;
using Assets.Scripts.Inventory__Items__Pickups.Weapons;
using Assets.Scripts.Managers;
using Assets.Scripts.Utility;
using Assets.Scripts._Data.MapsAndStages;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BonkCoop.Net;
using BonkCoop.Patches;
using BonkCoop.Run;
using BonkCoop.Steam;
using BonkCoop.Sync;
using BonkCoop.UI;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BonkCoop")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.3.0")]
[assembly: AssemblyInformationalVersion("0.2.3")]
[assembly: AssemblyProduct("BonkCoop")]
[assembly: AssemblyTitle("BonkCoop")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.3.0")]
[module: UnverifiableCode]
[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 BonkCoop
{
	public class CoopManager : MonoBehaviour
	{
		private const float SendInterval = 0.05f;

		private static readonly Vector3 SoloGhostOffset = new Vector3(2.5f, 0f, 0f);

		private static CoopManager _instance;

		private ITransport _transport;

		private readonly Dictionary<ulong, RemotePlayer> _remotes = new Dictionary<ulong, RemotePlayer>();

		private float _nextSend;

		private uint _seq;

		private int _sent;

		private int _received;

		private string _lastError;

		private bool? _bgBefore;

		private GUIStyle _tagStyle;

		public static IEnumerable<RemotePlayer> Remotes
		{
			get
			{
				if (!((Object)(object)_instance != (Object)null))
				{
					return Array.Empty<RemotePlayer>();
				}
				return _instance._remotes.Values;
			}
		}

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

		public static void ToggleSoloTest()
		{
			_instance?.SetSoloTest(!Plugin.SoloTestMode.Value);
		}

		private void Update()
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			_instance = this;
			try
			{
				MultiplayerMenu.Tick();
				SteamLobby.Tick();
				SeedWatch.Tick();
				MultiplayerScreen.Tick();
				UiKit.TickHover();
				HandleKeys();
				EnsureTransport();
				if (_transport == null)
				{
					CoopNet.Transport = null;
					EnemySync.Reset();
					MinimapMarkers.Clear();
					return;
				}
				_transport.Tick();
				MyPlayer localPlayer = GetLocalPlayer();
				if ((Object)(object)localPlayer != (Object)null && Time.unscaledTime >= _nextSend)
				{
					_nextSend = Time.unscaledTime + 0.05f;
					SendLocalState(localPlayer);
				}
				ReceiveAll((Object)(object)localPlayer != (Object)null);
				if ((Object)(object)localPlayer == (Object)null)
				{
					ClearRemotes();
				}
				else
				{
					PruneRemotes();
					foreach (RemotePlayer value in _remotes.Values)
					{
						value.Update();
					}
				}
				MinimapMarkers.Tick(localPlayer);
				DownedSync.Tick(localPlayer);
				StageSync.Tick(localPlayer);
				PartyHud.Tick(localPlayer);
				EnemySync.Tick(_transport, localPlayer);
			}
			catch (Exception ex)
			{
				if (_lastError != ex.Message)
				{
					_lastError = ex.Message;
					ManualLogSource log = Plugin.Log;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(19, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("CoopManager error: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					log.LogError(val);
				}
			}
		}

		private void HandleKeys()
		{
			if (Input.GetKeyDown((KeyCode)289))
			{
				SetSoloTest(!Plugin.SoloTestMode.Value);
			}
			if (Input.GetKeyDown((KeyCode)288))
			{
				Plugin.ShowOverlay.Value = !Plugin.ShowOverlay.Value;
			}
		}

		private void SetSoloTest(bool on)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Plugin.SoloTestMode.Value = on;
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Solo test mode: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(on ? "ON" : "OFF");
			}
			log.LogInfo(val);
			ShutdownTransport();
		}

		private void EnsureTransport()
		{
			bool flag = SteamLobby.InLobby && SteamLobby.Members.Count > 1;
			bool flag2 = !flag && Plugin.SoloTestMode.Value;
			if (_transport is SteamTransport && !flag)
			{
				ShutdownTransport();
			}
			if (_transport is LoopbackTransport && !flag2)
			{
				ShutdownTransport();
			}
			if (_transport == null)
			{
				if (flag)
				{
					_transport = new SteamTransport();
					Plugin.Log.LogInfo((object)"Started Steam transport");
				}
				else if (flag2)
				{
					_transport = new LoopbackTransport();
					Plugin.Log.LogInfo((object)"Started solo test transport");
				}
			}
			CoopNet.Transport = _transport;
			KeepRunningInBackground(flag);
			if (_transport is LoopbackTransport loopbackTransport)
			{
				loopbackTransport.LatencyMs = Math.Max(0, Plugin.FakeLatencyMs.Value);
				loopbackTransport.LossPercent = Math.Clamp(Plugin.FakePacketLossPercent.Value, 0, 90);
			}
		}

		private void KeepRunningInBackground(bool coop)
		{
			try
			{
				if (coop && !_bgBefore.HasValue)
				{
					_bgBefore = Application.runInBackground;
					Application.runInBackground = true;
				}
				else if (!coop && _bgBefore.HasValue)
				{
					Application.runInBackground = _bgBefore.Value;
					_bgBefore = null;
				}
			}
			catch (Exception ex)
			{
				LogOnce.Warn("runInBackground: " + ex.Message);
			}
		}

		private void ShutdownTransport()
		{
			_transport?.Dispose();
			_transport = null;
			ClearRemotes();
		}

		private static MyPlayer GetLocalPlayer()
		{
			MyPlayer instance = MyPlayer.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerRenderer == (Object)null)
			{
				return null;
			}
			return instance;
		}

		private void SendLocalState(MyPlayer player)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)player.playerRenderer).transform;
			int value = 0;
			int value2 = 0;
			try
			{
				PlayerHealth val = ((player.inventory != null) ? player.inventory.playerHealth : null);
				if (val != null)
				{
					value = val.hp;
					value2 = val.maxHp;
				}
			}
			catch
			{
			}
			PlayerStatePacket playerStatePacket = new PlayerStatePacket
			{
				Seq = ++_seq,
				Position = transform.position,
				Yaw = transform.eulerAngles.y,
				Hp = (short)Math.Clamp(value, 0, 32767),
				MaxHp = (short)Math.Clamp(value2, 0, 32767),
				Flags = (DownedSync.Downed ? ((byte)1) : ((byte)0))
			};
			_transport.Send(playerStatePacket.Write());
			_sent++;
		}

		private void ReceiveAll(bool inRun)
		{
			int num = 400;
			ulong fromPeer;
			byte[] data;
			while (num-- > 0 && _transport.TryReceive(out fromPeer, out data))
			{
				_received++;
				if (data != null && data.Length != 0)
				{
					try
					{
						HandlePacket(fromPeer, data, inRun);
					}
					catch (Exception e)
					{
						LogOnce.Error($"Message {((data.Length != 0) ? data[0] : 0)}", e);
					}
				}
			}
		}

		private void HandlePacket(ulong from, byte[] data, bool inRun)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			using BinaryReader binaryReader = new BinaryReader(new MemoryStream(data));
			PacketType packetType = (PacketType)binaryReader.ReadByte();
			if (!EnemySync.Handle(packetType, binaryReader, from) && !StageSync.Handle(packetType, binaryReader, from) && !InteractSync.Handle(packetType, binaryReader, from) && !DownedSync.Handle(packetType, binaryReader, from) && packetType == PacketType.PlayerState && inRun)
			{
				PlayerStatePacket playerStatePacket = PlayerStatePacket.Read(binaryReader);
				Vector3 val = playerStatePacket.Position;
				if (_transport is LoopbackTransport)
				{
					val += SoloGhostOffset;
				}
				RemotePlayer remote = GetRemote(from);
				if (string.IsNullOrEmpty(remote.Character) && !(_transport is LoopbackTransport))
				{
					remote.Character = CharacterOf(from);
					remote.Skin = SkinOf(from);
				}
				remote.AddState(playerStatePacket.Seq, val, playerStatePacket.Yaw);
				remote.Hp = playerStatePacket.Hp;
				remote.MaxHp = playerStatePacket.MaxHp;
				remote.Downed = (playerStatePacket.Flags & 1) != 0;
			}
		}

		private void PruneRemotes()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			List<ulong> list = null;
			bool flag = _transport is SteamTransport;
			foreach (KeyValuePair<ulong, RemotePlayer> kv in _remotes)
			{
				bool num = !flag || SteamLobby.Members.Exists((SteamLobby.Member m) => m.Id == kv.Key);
				bool flag2 = Time.unscaledTime - kv.Value.LastHeard > 3f;
				if (!num || flag2)
				{
					(list ?? (list = new List<ulong>())).Add(kv.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			bool flag3 = default(bool);
			foreach (ulong item in list)
			{
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag3);
				if (flag3)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Player ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(_remotes[item].DisplayName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" left the run");
				}
				log.LogInfo(val);
				_remotes[item].Destroy();
				_remotes.Remove(item);
			}
		}

		private RemotePlayer GetRemote(ulong peer)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			if (!_remotes.TryGetValue(peer, out var value))
			{
				string text = ((_transport is LoopbackTransport) ? "Ghost (you)" : SteamLobby.NameOf(peer));
				value = new RemotePlayer(peer, text);
				value.Character = ((_transport is LoopbackTransport) ? SteamLobby.MyCharacter : CharacterOf(peer));
				value.Skin = ((_transport is LoopbackTransport) ? SteamLobby.MySkin : SkinOf(peer));
				_remotes[peer] = value;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(19, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("New remote player: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
				}
				log.LogInfo(val);
			}
			return value;
		}

		private static string SkinOf(ulong peer)
		{
			foreach (SteamLobby.Member member in SteamLobby.Members)
			{
				if (member.Id == peer)
				{
					return member.SkinName;
				}
			}
			return "";
		}

		private static string CharacterOf(ulong peer)
		{
			foreach (SteamLobby.Member member in SteamLobby.Members)
			{
				if (member.Id == peer)
				{
					return member.Character;
				}
			}
			return "";
		}

		private void ClearRemotes()
		{
			foreach (RemotePlayer value in _remotes.Values)
			{
				value.Destroy();
			}
			_remotes.Clear();
		}

		private void OnGUI()
		{
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			DrawNameTags();
			if (Plugin.ShowOverlay.Value)
			{
				string value = _transport?.Name ?? (SteamLobby.InLobby ? "Lobby (waiting for players)" : "Offline");
				string value2 = ((_transport is LoopbackTransport) ? $"  |  fake lag {Plugin.FakeLatencyMs.Value}ms, loss {Plugin.FakePacketLossPercent.Value}%" : "");
				string text = $"BonkCoop {"0.2.3"}  |  {value}{value2}\nplayers: {_remotes.Count}  sent: {_sent}  recv: {_received}\n" + "F8 solo test on/off   F7 hide this";
				if (_lastError != null)
				{
					text = text + "\nERROR: " + _lastError;
				}
				float num = ((_lastError != null) ? 82 : 64);
				float num2 = (float)Screen.height - num - 10f;
				GUI.Box(new Rect(10f, num2, 430f, num), "");
				GUI.Label(new Rect(18f, num2 + 4f, 420f, 80f), text);
			}
		}

		private void DrawNameTags()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			if (_remotes.Count == 0)
			{
				return;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return;
			}
			if (_tagStyle == null)
			{
				_tagStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 16
				};
				_tagStyle.normal.textColor = Color.white;
			}
			Rect val2 = default(Rect);
			foreach (RemotePlayer value in _remotes.Values)
			{
				Vector3 val = main.WorldToScreenPoint(value.CurrentPosition + Vector3.up * 2.4f);
				if (!(val.z <= 0f))
				{
					string text = (value.Downed ? (value.DisplayName + " (DOWN)") : value.DisplayName);
					((Rect)(ref val2))..ctor(val.x - 100f, (float)Screen.height - val.y - 12f, 200f, 24f);
					Rect val3 = new Rect(((Rect)(ref val2)).x + 1f, ((Rect)(ref val2)).y + 1f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height);
					Color textColor = _tagStyle.normal.textColor;
					_tagStyle.normal.textColor = new Color(0f, 0f, 0f, 0.8f);
					GUI.Label(val3, text, _tagStyle);
					_tagStyle.normal.textColor = (Color)(value.Downed ? new Color(1f, 0.4f, 0.35f) : textColor);
					GUI.Label(val2, text, _tagStyle);
					_tagStyle.normal.textColor = textColor;
				}
			}
		}

		private void LateUpdate()
		{
			try
			{
				MultiplayerScreen.LateTick();
			}
			catch (Exception e)
			{
				LogOnce.Error("Lobby screen", e);
			}
			EnemySync.LateTick();
			foreach (RemotePlayer value in _remotes.Values)
			{
				try
				{
					value.LateUpdate();
				}
				catch (Exception e2)
				{
					LogOnce.Error("Remote late", e2);
				}
			}
			try
			{
				DownedSync.LateTick(GetLocalPlayer());
			}
			catch (Exception e3)
			{
				LogOnce.Error("Downed late", e3);
			}
		}

		private void OnDestroy()
		{
			ShutdownTransport();
		}
	}
	public static class MultiplayerMenu
	{
		private static IntPtr _injectedInto;

		private static float _nextCheck;

		private static MainMenu _menu;

		public static bool SuppressAutoOpen;

		public static void Tick()
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			if ((Object)(object)_menu != (Object)null && !SuppressAutoOpen && !MultiplayerScreen.IsOpen && SteamLobby.State != SteamLobby.LobbyState.None)
			{
				MultiplayerScreen.Open(_menu);
			}
			if (Time.unscaledTime < _nextCheck)
			{
				return;
			}
			_nextCheck = Time.unscaledTime + 0.5f;
			MainMenu val = Object.FindObjectOfType<MainMenu>();
			if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).Pointer == _injectedInto || (Object)(object)val.btnPlay == (Object)null || (Object)(object)val.btnUnlocks == (Object)null)
			{
				return;
			}
			_injectedInto = ((Il2CppObjectBase)val).Pointer;
			_menu = val;
			SuppressAutoOpen = false;
			try
			{
				UiKit.Capture(val);
				AddButton(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Couldn't add Multiplayer button: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log.LogError(val2);
			}
		}

		private static void AddButton(MainMenu menu)
		{
			//IL_00e7: 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_0104: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_0182: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected O, but got Unknown
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)menu.btnPlay).gameObject;
			GameObject gameObject2 = menu.btnUnlocks.gameObject;
			Transform parent = gameObject.transform.parent;
			GameObject val = Object.Instantiate<GameObject>(gameObject, parent);
			((Object)val).name = "B_Multiplayer";
			UiKit.StripGameScripts(val);
			RectTransform component = val.GetComponent<RectTransform>();
			TMP_Text componentInChildren = gameObject2.GetComponentInChildren<TMP_Text>(true);
			float num = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.fontSize : 60f);
			float num2 = 0f;
			foreach (TMP_Text componentsInChild in val.GetComponentsInChildren<TMP_Text>(true))
			{
				componentsInChild.text = "MULTIPLAYER";
				componentsInChild.enableAutoSizing = false;
				componentsInChild.fontSize = num;
				componentsInChild.ForceMeshUpdate(false, false);
				num2 = Mathf.Max(num2, componentsInChild.preferredWidth);
				RectTransform rectTransform = componentsInChild.rectTransform;
				if (((Il2CppObjectBase)rectTransform).Pointer != ((Il2CppObjectBase)component).Pointer)
				{
					rectTransform.anchorMin = new Vector2(0f, rectTransform.anchorMin.y);
					rectTransform.anchorMax = new Vector2(1f, rectTransform.anchorMax.y);
					rectTransform.offsetMin = new Vector2(0f, rectTransform.offsetMin.y);
					rectTransform.offsetMax = new Vector2(0f, rectTransform.offsetMax.y);
					componentsInChild.alignment = (TextAlignmentOptions)514;
				}
			}
			if ((Object)(object)component != (Object)null)
			{
				float num3 = Mathf.Max(component.sizeDelta.x, num2 + 70f);
				component.sizeDelta = new Vector2(num3, component.sizeDelta.y);
				LayoutElement component2 = val.GetComponent<LayoutElement>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.preferredWidth = num3;
					component2.minWidth = num3;
				}
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(47, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Multiplayer button: font ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(num);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", text width ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(num2);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", button ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Vector2?>((component != null) ? new Vector2?(component.sizeDelta) : ((Vector2?)null));
			}
			log.LogInfo(val2);
			Button val3 = val.GetComponentInChildren<Button>(true);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.AddComponent<Button>();
			}
			val3.onClick = new ButtonClickedEvent();
			((UnityEvent)val3.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				MultiplayerScreen.Open(_menu);
			}));
			val.transform.SetSiblingIndex(gameObject2.transform.GetSiblingIndex());
			if ((Object)(object)component != (Object)null)
			{
				UiKit.TrackHover(component);
			}
			Plugin.Log.LogInfo((object)"Added MULTIPLAYER button to main menu");
		}
	}
	[BepInPlugin("BonkCoop", "BonkCoop", "0.2.3")]
	public class Plugin : BasePlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> SoloTestMode;

		internal static ConfigEntry<int> FakeLatencyMs;

		internal static ConfigEntry<int> FakePacketLossPercent;

		internal static ConfigEntry<bool> ShowOverlay;

		internal static ConfigEntry<int> DebugSharedSeed;

		public override void Load()
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Expected O, but got Unknown
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected O, but got Unknown
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			SoloTestMode = ((BasePlugin)this).Config.Bind<bool>("Testing", "SoloTestMode", false, "Echo your own movement back as a ghost player, to test syncing without a second player. Toggle in-game with F8.");
			FakeLatencyMs = ((BasePlugin)this).Config.Bind<int>("Testing", "FakeLatencyMs", 100, "Pretend network delay for solo test mode, in milliseconds.");
			FakePacketLossPercent = ((BasePlugin)this).Config.Bind<int>("Testing", "FakePacketLossPercent", 0, "Pretend percentage of lost packets for solo test mode (0-90).");
			DebugSharedSeed = ((BasePlugin)this).Config.Bind<int>("Testing", "DebugSharedSeed", 0, "If not 0, the host always uses this shared seed (for checking that the same seed gives the same map).");
			ShowOverlay = ((BasePlugin)this).Config.Bind<bool>("General", "ShowOverlay", false, "Show the BonkCoop status box in the corner. Toggle in-game with F7.");
			Harmony val = new Harmony("BonkCoop");
			SharedCodeCheck.Build();
			int num = 0;
			int num2 = 0;
			Type[] types = typeof(Plugin).Assembly.GetTypes();
			bool flag = default(bool);
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length == 0)
				{
					continue;
				}
				try
				{
					MethodBase methodBase = null;
					try
					{
						HarmonyMethod val2 = HarmonyMethod.Merge(HarmonyMethodExtensions.GetFromType(type));
						if (val2.declaringType != null && val2.methodName != null)
						{
							methodBase = AccessTools.Method(val2.declaringType, val2.methodName, val2.argumentTypes, (Type[])null);
						}
					}
					catch
					{
					}
					if (methodBase != null && SharedCodeCheck.IsShared(methodBase))
					{
						ManualLogSource log = Log;
						BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(58, 3, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Skipped hook ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(type.Name);
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(methodBase.DeclaringType?.Name);
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(".");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(methodBase.Name);
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" shares its code with other game functions");
						}
						log.LogWarning(val3);
						num2++;
					}
					else
					{
						val.CreateClassProcessor(type).Patch();
						num++;
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log2 = Log;
					BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(15, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Patch ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(type.Name);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" failed: ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
					}
					log2.LogWarning(val3);
				}
			}
			ManualLogSource log3 = Log;
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(34, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Hooks: ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" added, ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num2);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" skipped for safety");
			}
			log3.LogInfo(val4);
			InteractSync.PatchAll(val);
			((BasePlugin)this).AddComponent<CoopManager>();
			ManualLogSource log4 = Log;
			val4 = new BepInExInfoLogInterpolatedStringHandler(17, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("BonkCoop ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("0.2.3");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" loaded!");
			}
			log4.LogInfo(val4);
		}
	}
	public class RemotePlayer
	{
		private struct Snapshot
		{
			public float Time;

			public Vector3 Pos;

			public float Yaw;
		}

		private const float InterpDelay = 0.1f;

		private bool _downed;

		private GameObject _marker;

		private readonly List<Renderer> _hiddenRenderers = new List<Renderer>();

		private readonly List<Snapshot> _buffer = new List<Snapshot>();

		private GameObject _body;

		private bool _isCapsule;

		private PlayerRenderer _renderer;

		private Vector3 _lastPos;

		private bool _moving;

		private float _movingSince;

		private float _stoppedSince;

		private float _nextModelRetry;

		public ulong PeerId { get; }

		public string DisplayName { get; set; }

		public uint LastSeq { get; private set; }

		public int Hp { get; set; }

		public int MaxHp { get; set; }

		public string Character { get; set; } = "";

		public string Skin { get; set; } = "";

		public bool Downed
		{
			get
			{
				return _downed;
			}
			set
			{
				if (_downed != value)
				{
					_downed = value;
					RefreshDownedLook();
				}
			}
		}

		public float LastHeard { get; private set; }

		public Vector3 CurrentPosition
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_body != (Object)null))
				{
					return Vector3.zero;
				}
				return _body.transform.position;
			}
		}

		public float CurrentYaw { get; private set; }

		public Transform Root
		{
			get
			{
				if (!((Object)(object)_body != (Object)null))
				{
					return null;
				}
				return _body.transform;
			}
		}

		public Rigidbody Body { get; private set; }

		public RemotePlayer(ulong peerId, string name)
		{
			PeerId = peerId;
			DisplayName = name;
		}

		public void AddState(uint seq, Vector3 pos, float yaw)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (seq > LastSeq || LastSeq == 0)
			{
				LastSeq = seq;
				LastHeard = Time.unscaledTime;
				_buffer.Add(new Snapshot
				{
					Time = Time.unscaledTime,
					Pos = pos,
					Yaw = yaw
				});
				if (_buffer.Count > 30)
				{
					_buffer.RemoveAt(0);
				}
			}
		}

		public void Update()
		{
			//IL_007e: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_0104: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			if (_buffer.Count != 0)
			{
				EnsureBody();
				float num = Time.unscaledTime - 0.1f;
				int num2 = _buffer.Count - 1;
				while (num2 > 0 && _buffer[num2 - 1].Time > num)
				{
					num2--;
				}
				Vector3 val;
				float num3;
				if (num2 == 0 || _buffer[num2].Time <= num)
				{
					Snapshot snapshot = _buffer[_buffer.Count - 1];
					val = snapshot.Pos;
					num3 = snapshot.Yaw;
				}
				else
				{
					Snapshot snapshot2 = _buffer[num2 - 1];
					Snapshot snapshot3 = _buffer[num2];
					float num4 = Mathf.InverseLerp(snapshot2.Time, snapshot3.Time, num);
					val = Vector3.Lerp(snapshot2.Pos, snapshot3.Pos, num4);
					num3 = Mathf.LerpAngle(snapshot2.Yaw, snapshot3.Yaw, num4);
				}
				Transform transform = _body.transform;
				CurrentYaw = num3;
				if (_downed)
				{
					transform.position = val + Vector3.up * (_isCapsule ? 0.5f : 0.25f);
					transform.rotation = Quaternion.Euler(0f, num3, 0f) * Quaternion.Euler(-90f, 0f, 0f);
					return;
				}
				transform.position = (_isCapsule ? (val + Vector3.up) : val);
				transform.rotation = Quaternion.Euler(0f, num3, 0f);
				Animate(val, num3);
				RetryRealModel();
			}
		}

		private void RetryRealModel()
		{
			//IL_007e: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			if (!_isCapsule || Time.unscaledTime < _nextModelRetry)
			{
				return;
			}
			_nextModelRetry = Time.unscaledTime + 2f;
			GameObject val = null;
			try
			{
				val = SpawnCharacterModel();
			}
			catch (Exception ex)
			{
				LogOnce.Warn("Model retry for " + DisplayName + ": " + ex.Message);
			}
			if (!((Object)(object)val == (Object)null))
			{
				GameObject body = _body;
				_body = val;
				_body.transform.SetPositionAndRotation(body.transform.position - Vector3.up, body.transform.rotation);
				Object.Destroy((Object)(object)body);
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(38, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Replaced ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(DisplayName);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'s stand-in with their ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Character);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" model");
				}
				log.LogInfo(val2);
				AttachBody();
			}
		}

		private void Animate(Vector3 pos, float yaw)
		{
			//IL_003d: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_renderer == (Object)null)
			{
				return;
			}
			try
			{
				if (_renderer.isDamageFlash)
				{
					_renderer.ResetMaterial();
				}
			}
			catch
			{
			}
			float num = Mathf.Max(Time.deltaTime, 0.0001f);
			Vector3 val = Vector3.ProjectOnPlane(pos - _lastPos, Vector3.up);
			float num2 = ((Vector3)(ref val)).magnitude / num;
			_lastPos = pos;
			bool flag = num2 > 0.6f;
			if (flag)
			{
				_stoppedSince = Time.time;
			}
			else
			{
				_movingSince = Time.time;
			}
			if (flag != _moving && (flag ? (Time.time - _movingSince) : (Time.time - _stoppedSince)) > 0.08f)
			{
				_moving = flag;
				try
				{
					_renderer.ForceMoving(_moving);
				}
				catch
				{
				}
			}
			try
			{
				_renderer.ForceRotation(Quaternion.Euler(0f, yaw, 0f) * Vector3.forward);
			}
			catch
			{
			}
		}

		private void EnsureBody()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			if ((Object)(object)_body != (Object)null)
			{
				return;
			}
			try
			{
				_body = SpawnCharacterModel();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(37, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Couldn't build character model for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(DisplayName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val);
				if ((Object)(object)_body != (Object)null)
				{
					Object.Destroy((Object)(object)_body);
				}
				_body = null;
				_renderer = null;
			}
			if ((Object)(object)_body == (Object)null)
			{
				MakeCapsule();
			}
			AttachBody();
		}

		private void AttachBody()
		{
			Body = _body.GetComponent<Rigidbody>();
			if ((Object)(object)Body == (Object)null)
			{
				Body = _body.AddComponent<Rigidbody>();
			}
			Body.isKinematic = true;
			Body.useGravity = false;
			RefreshDownedLook();
		}

		private GameObject SpawnCharacterModel()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			CharacterData val = UiKit.FindCharacter(Character);
			MyPlayer instance = MyPlayer.Instance;
			bool flag = default(bool);
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(35, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("No model for ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(DisplayName);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": unknown character '");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Character);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'");
				}
				log.LogWarning(val2);
				return null;
			}
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerRenderer == (Object)null)
			{
				ManualLogSource log2 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(45, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("No model for ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(DisplayName);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": your own model isn't ready yet");
				}
				log2.LogWarning(val2);
				return null;
			}
			GameObject val3 = new GameObject("BonkCoop_ModelHolder");
			val3.SetActive(false);
			GameObject val4 = Object.Instantiate<GameObject>(((Component)instance.playerRenderer).gameObject, val3.transform);
			((Object)val4).name = $"BonkCoop_Remote_{PeerId}";
			foreach (Component componentsInChild in val4.GetComponentsInChildren<Component>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null))
				{
					Type il2CppType = ((Object)componentsInChild).GetIl2CppType();
					string text = il2CppType.Namespace ?? "";
					string name = ((MemberInfo)il2CppType).Name;
					bool flag2 = text.StartsWith("UnityEngine") || text.StartsWith("TMPro");
					if (!(name == "PlayerRenderer") && !(name == "Outline") && (!flag2 || !((Object)(object)((Il2CppObjectBase)componentsInChild).TryCast<Collider>() == (Object)null) || !((Object)(object)((Il2CppObjectBase)componentsInChild).TryCast<Rigidbody>() == (Object)null)))
					{
						Object.DestroyImmediate((Object)(object)componentsInChild);
					}
				}
			}
			val4.transform.SetParent((Transform)null, true);
			Object.Destroy((Object)(object)val3);
			val4.SetActive(true);
			_renderer = val4.GetComponent<PlayerRenderer>();
			if ((Object)(object)_renderer != (Object)null)
			{
				_renderer.playerMovement = null;
				UiKit.DressModel(val4, _renderer, val, UiKit.FindSkin(Skin));
			}
			else
			{
				ManualLogSource log3 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(41, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Model copy for ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(DisplayName);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" has no character renderer");
				}
				log3.LogWarning(val2);
			}
			_isCapsule = false;
			ManualLogSource log4 = Plugin.Log;
			BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(17, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Built ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(Character);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" model for ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(DisplayName);
			}
			log4.LogInfo(val5);
			return val4;
		}

		private void MakeCapsule()
		{
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			_isCapsule = true;
			_renderer = null;
			_body = GameObject.CreatePrimitive((PrimitiveType)1);
			((Object)_body).name = $"BonkCoop_Remote_{PeerId}";
			Object.DontDestroyOnLoad((Object)(object)_body);
			Collider component = _body.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			Renderer component2 = _body.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				Shader val = Shader.Find("Unlit/Color");
				if ((Object)(object)val != (Object)null)
				{
					component2.material = new Material(val);
				}
				component2.material.color = new Color(0.24f, 0.82f, 0.78f);
			}
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			Collider component3 = obj.GetComponent<Collider>();
			if ((Object)(object)component3 != (Object)null)
			{
				Object.Destroy((Object)(object)component3);
			}
			obj.transform.SetParent(_body.transform, false);
			obj.transform.localPosition = new Vector3(0f, 0.5f, 0.5f);
			obj.transform.localScale = new Vector3(0.3f, 0.3f, 0.4f);
		}

		private void RefreshDownedLook()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			if ((Object)(object)_body == (Object)null)
			{
				return;
			}
			if ((Object)(object)_renderer != (Object)null)
			{
				try
				{
					((Behaviour)_renderer).enabled = !_downed;
					if (_downed)
					{
						_renderer.ForceMoving(false);
					}
				}
				catch
				{
				}
			}
			if (_downed && (Object)(object)_marker == (Object)null)
			{
				_marker = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)_marker).name = "BonkCoop_DownedMarker";
				Collider component = _marker.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				Renderer component2 = _marker.GetComponent<Renderer>();
				Shader val = Shader.Find("Unlit/Color");
				if ((Object)(object)val != (Object)null)
				{
					component2.material = new Material(val);
				}
				component2.material.color = new Color(1f, 0.25f, 0.2f);
			}
			if ((Object)(object)_marker != (Object)null)
			{
				_marker.SetActive(_downed);
			}
		}

		public void LateUpdate()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_marker == (Object)null) && _downed && !((Object)(object)_body == (Object)null))
			{
				float num = Mathf.Sin(Time.unscaledTime * 3f) * 0.15f;
				_marker.transform.position = CurrentPosition + Vector3.up * (2.2f + num);
				_marker.transform.localScale = Vector3.one * 0.45f;
			}
		}

		public void Destroy()
		{
			if ((Object)(object)_body != (Object)null)
			{
				Object.Destroy((Object)(object)_body);
			}
			if ((Object)(object)_marker != (Object)null)
			{
				Object.Destroy((Object)(object)_marker);
			}
			_body = null;
			Body = null;
			_marker = null;
			_hiddenRenderers.Clear();
			_buffer.Clear();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BonkCoop";

		public const string PLUGIN_NAME = "BonkCoop";

		public const string PLUGIN_VERSION = "0.2.3";
	}
}
namespace BonkCoop.UI
{
	public static class LobbyLineup
	{
		private class Slot
		{
			public GameObject Model;

			public string Character = "";

			public string Skin = "";

			public TextMeshProUGUI Tag;
		}

		private const float Spacing = 1.9f;

		private static readonly Dictionary<ulong, Slot> _slots = new Dictionary<ulong, Slot>();

		private static CharacterDisplay _display;

		private static GameObject _template;

		private static Vector3 _basePos;

		private static Quaternion _baseRot;

		private static bool _shown;

		public static void Tick(RectTransform tagParent, Canvas canvas)
		{
			//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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: 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_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			if (!FindTemplate())
			{
				return;
			}
			if (!_shown)
			{
				_shown = true;
				_basePos = _template.transform.position;
				_baseRot = _template.transform.rotation;
				_template.SetActive(false);
			}
			if (_template.activeSelf)
			{
				_template.SetActive(false);
			}
			HashSet<ulong> hashSet = new HashSet<ulong>();
			foreach (SteamLobby.Member member2 in SteamLobby.Members)
			{
				hashSet.Add(member2.Id);
			}
			List<ulong> list = new List<ulong>();
			foreach (KeyValuePair<ulong, Slot> slot2 in _slots)
			{
				if (!hashSet.Contains(slot2.Key))
				{
					list.Add(slot2.Key);
				}
			}
			foreach (ulong item in list)
			{
				DestroySlot(_slots[item]);
				_slots.Remove(item);
			}
			List<SteamLobby.Member> list2 = new List<SteamLobby.Member>();
			foreach (SteamLobby.Member member3 in SteamLobby.Members)
			{
				if (member3.Character.Length > 0)
				{
					list2.Add(member3);
				}
			}
			Camera main = Camera.main;
			Vector3 val;
			if (!((Object)(object)main != (Object)null))
			{
				val = Vector3.right;
			}
			else
			{
				Vector3 val2 = Vector3.ProjectOnPlane(((Component)main).transform.right, Vector3.up);
				val = ((Vector3)(ref val2)).normalized;
			}
			Vector3 val3 = val;
			for (int i = 0; i < list2.Count; i++)
			{
				SteamLobby.Member member = list2[i];
				if (!_slots.TryGetValue(member.Id, out var value))
				{
					value = (_slots[member.Id] = new Slot());
				}
				if ((Object)(object)value.Model == (Object)null || value.Character != member.Character || value.Skin != member.SkinName)
				{
					if ((Object)(object)value.Model != (Object)null)
					{
						Object.Destroy((Object)(object)value.Model);
					}
					value.Model = SpawnModel(member.Character, member.SkinName);
					value.Character = member.Character;
					value.Skin = member.SkinName;
				}
				if ((Object)(object)value.Model == (Object)null)
				{
					continue;
				}
				float num = ((float)i - (float)(list2.Count - 1) / 2f) * 1.9f;
				Vector3 val4 = _basePos + val3 * num;
				value.Model.transform.position = val4;
				if ((Object)(object)main != (Object)null)
				{
					Vector3 val5 = Vector3.ProjectOnPlane(((Component)main).transform.position - val4, Vector3.up);
					if (((Vector3)(ref val5)).sqrMagnitude > 0.01f)
					{
						value.Model.transform.rotation = Quaternion.LookRotation(val5);
					}
				}
				else
				{
					value.Model.transform.rotation = _baseRot;
				}
				value.Model.SetActive(true);
				UpdateTag(value, member, tagParent, canvas, main);
			}
			foreach (SteamLobby.Member member4 in SteamLobby.Members)
			{
				if (member4.Character.Length == 0 && _slots.TryGetValue(member4.Id, out var value2))
				{
					DestroySlot(value2);
					_slots.Remove(member4.Id);
				}
			}
		}

		public static void Hide()
		{
			foreach (Slot value in _slots.Values)
			{
				DestroySlot(value);
			}
			_slots.Clear();
			if (_shown && (Object)(object)_template != (Object)null)
			{
				_template.SetActive(true);
			}
			_shown = false;
		}

		private static bool FindTemplate()
		{
			if ((Object)(object)_template != (Object)null)
			{
				return true;
			}
			_display = Object.FindObjectOfType<CharacterDisplay>();
			if ((Object)(object)_display == (Object)null || (Object)(object)_display.playerRenderer == (Object)null)
			{
				return false;
			}
			_template = ((Component)_display.playerRenderer).gameObject;
			return true;
		}

		private static GameObject SpawnModel(string character, string skinName)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			CharacterData val = UiKit.FindCharacter(character);
			if ((Object)(object)val == (Object)null)
			{
				LogOnce.Warn("Unknown character '" + character + "'");
				return null;
			}
			bool activeSelf = _template.activeSelf;
			_template.SetActive(true);
			GameObject val2 = Object.Instantiate<GameObject>(_template, _template.transform.parent);
			_template.SetActive(activeSelf);
			((Object)val2).name = "BonkCoop_Lobby_" + character;
			foreach (MonoBehaviour componentsInChild in val2.GetComponentsInChildren<MonoBehaviour>(true))
			{
				switch (((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name)
				{
				case "CharacterDisplay":
				case "CharacterSpin":
				case "SpinAroundCharacter":
					Object.DestroyImmediate((Object)(object)componentsInChild);
					break;
				}
			}
			PlayerRenderer component = val2.GetComponent<PlayerRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				try
				{
					UiKit.DressModel(val2, component, val, UiKit.FindSkin(skinName));
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Couldn't dress lobby model: ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
					}
					log.LogWarning(val3);
				}
			}
			return val2;
		}

		private static void UpdateTag(Slot slot, SteamLobby.Member m, RectTransform parent, Canvas canvas, Camera cam)
		{
			//IL_00b0: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)slot.Tag == (Object)null)
			{
				slot.Tag = UiKit.MakeLabel((Transform)(object)parent, "", 0f, 0f, 320f, 70f, 28f, (TextAlignmentOptions)1026);
				RectTransform rectTransform = ((TMP_Text)slot.Tag).rectTransform;
				Vector2 anchorMin = (rectTransform.anchorMax = Vector2.zero);
				rectTransform.anchorMin = anchorMin;
				rectTransform.pivot = new Vector2(0.5f, 0f);
			}
			Color color;
			string value = MultiplayerScreen.StatusText(m, out color);
			((TMP_Text)slot.Tag).text = $"{m.Name}\n<size=70%><color=#{Hex(color)}>{value}</color></size>";
			if (!((Object)(object)cam == (Object)null))
			{
				Vector3 val = cam.WorldToScreenPoint(HeadTop(slot.Model) + Vector3.up * 0.25f);
				((Component)slot.Tag).gameObject.SetActive(val.z > 0f);
				float num = (((Object)(object)canvas != (Object)null) ? canvas.scaleFactor : 1f);
				((TMP_Text)slot.Tag).rectTransform.anchoredPosition = new Vector2(val.x / num, val.y / num);
			}
		}

		private static Vector3 HeadTop(GameObject model)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			Bounds val = default(Bounds);
			foreach (Renderer componentsInChild in model.GetComponentsInChildren<Renderer>())
			{
				if (componentsInChild.enabled)
				{
					if (!flag)
					{
						val = componentsInChild.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(componentsInChild.bounds);
					}
				}
			}
			if (!flag)
			{
				return model.transform.position + Vector3.up * 2.3f;
			}
			return new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).max.y, ((Bounds)(ref val)).center.z);
		}

		private static string Hex(Color c)
		{
			//IL_000b: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			return $"{(int)(Mathf.Clamp01(c.r) * 255f):X2}{(int)(Mathf.Clamp01(c.g) * 255f):X2}{(int)(Mathf.Clamp01(c.b) * 255f):X2}";
		}

		private static void DestroySlot(Slot s)
		{
			if ((Object)(object)s.Model != (Object)null)
			{
				Object.Destroy((Object)(object)s.Model);
			}
			if ((Object)(object)s.Tag != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)s.Tag).gameObject);
			}
		}
	}
	public static class MinimapMarkers
	{
		private class Marker
		{
			public GameObject Root;

			public Material Fill;

			public Transform ArrowTarget;
		}

		private static readonly Color[] Palette = (Color[])(object)new Color[3]
		{
			new Color(0.35f, 1f, 0.45f),
			new Color(1f, 0.85f, 0.2f),
			new Color(0.8f, 0.5f, 1f)
		};

		private static readonly Color DownColor = new Color(1f, 0.2f, 0.15f);

		private static readonly Dictionary<ulong, Marker> _markers = new Dictionary<ulong, Marker>();

		private static MinimapCamera _cam;

		private static float _nextCamLookup;

		private static Mesh _arrowMesh;

		private static Shader _shader;

		public static Color ColorFor(ulong id)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (SteamLobby.Member member in SteamLobby.Members)
			{
				if (!member.IsMe)
				{
					if (member.Id == id)
					{
						return Palette[num % Palette.Length];
					}
					num++;
				}
			}
			return Palette[0];
		}

		public static void Tick(MyPlayer player)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				Clear();
				return;
			}
			try
			{
				if ((Object)(object)_cam == (Object)null)
				{
					if (Time.unscaledTime < _nextCamLookup)
					{
						return;
					}
					_nextCamLookup = Time.unscaledTime + 1f;
					_cam = Object.FindObjectOfType<MinimapCamera>();
					if ((Object)(object)_cam == (Object)null)
					{
						return;
					}
				}
				Transform playerIcon = _cam.playerIcon;
				if ((Object)(object)playerIcon == (Object)null)
				{
					return;
				}
				Renderer componentInChildren = ((Component)playerIcon).GetComponentInChildren<Renderer>(true);
				int layer = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).gameObject.layer : ((Component)playerIcon).gameObject.layer);
				float num = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).transform.position.y : playerIcon.position.y) - ((Component)player).transform.position.y;
				float num2 = 6f;
				if ((Object)(object)componentInChildren != (Object)null)
				{
					Bounds bounds = componentInChildren.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					num2 = Mathf.Clamp(Mathf.Max(size.x, size.z), 1f, 60f);
				}
				HashSet<ulong> hashSet = new HashSet<ulong>();
				foreach (RemotePlayer remote in CoopManager.Remotes)
				{
					if (!((Object)(object)remote.Root == (Object)null))
					{
						hashSet.Add(remote.PeerId);
						if (!_markers.TryGetValue(remote.PeerId, out var value) || (Object)(object)value.Root == (Object)null)
						{
							value = Make(layer);
							_markers[remote.PeerId] = value;
						}
						Transform transform = value.Root.transform;
						Vector3 currentPosition = remote.CurrentPosition;
						transform.position = new Vector3(currentPosition.x, currentPosition.y + num + 0.05f, currentPosition.z);
						transform.rotation = Quaternion.Euler(0f, remote.CurrentYaw, 0f);
						float num3 = num2 / 1.8f;
						if (remote.Downed)
						{
							num3 *= 1f + 0.25f * Mathf.Sin(Time.unscaledTime * 6f);
						}
						transform.localScale = Vector3.one * num3;
						value.Fill.color = (remote.Downed ? DownColor : ColorFor(remote.PeerId));
						UpdateEdgeArrow(value, remote.Downed ? remote.Root : null);
					}
				}
				List<ulong> list = null;
				foreach (ulong key in _markers.Keys)
				{
					if (!hashSet.Contains(key))
					{
						(list ?? (list = new List<ulong>())).Add(key);
					}
				}
				if (list == null)
				{
					return;
				}
				foreach (ulong item in list)
				{
					Remove(item);
				}
			}
			catch (Exception e)
			{
				LogOnce.Error("Minimap markers", e);
			}
		}

		private static void UpdateEdgeArrow(Marker mk, Transform target)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			IntPtr intPtr = (((Object)(object)mk.ArrowTarget != (Object)null) ? ((Il2CppObjectBase)mk.ArrowTarget).Pointer : IntPtr.Zero);
			IntPtr intPtr2 = (((Object)(object)target != (Object)null) ? ((Il2CppObjectBase)target).Pointer : IntPtr.Zero);
			if (intPtr == intPtr2)
			{
				return;
			}
			try
			{
				if ((Object)(object)mk.ArrowTarget != (Object)null && (Object)(object)_cam != (Object)null)
				{
					_cam.RemoveArrow(mk.ArrowTarget);
				}
				mk.ArrowTarget = null;
				if ((Object)(object)target != (Object)null && (Object)(object)_cam != (Object)null)
				{
					_cam.AddArrow(target, DownColor);
					mk.ArrowTarget = target;
				}
			}
			catch (Exception ex)
			{
				LogOnce.Warn("Minimap edge arrow: " + ex.Message);
				mk.ArrowTarget = target;
			}
		}

		private static Marker Make(int layer)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0054: 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_006e: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (_shader == null)
			{
				_shader = Shader.Find("Unlit/Color");
			}
			if (_arrowMesh == null)
			{
				_arrowMesh = BuildArrowMesh();
			}
			GameObject val = new GameObject("BonkCoop_MinimapTeammate");
			val.layer = layer;
			GameObject obj = MakePart(val.transform, layer, new Color(0f, 0f, 0f, 1f));
			obj.transform.localScale = Vector3.one * 1.3f;
			obj.transform.localPosition = new Vector3(0f, -0.02f, -0.05f);
			GameObject val2 = MakePart(val.transform, layer, Palette[0]);
			return new Marker
			{
				Root = val,
				Fill = ((Renderer)val2.GetComponent<MeshRenderer>()).material
			};
		}

		private static GameObject MakePart(Transform parent, int layer, Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			GameObject val = new GameObject("Arrow")
			{
				layer = layer
			};
			val.transform.SetParent(parent, false);
			val.AddComponent<MeshFilter>().sharedMesh = _arrowMesh;
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			Material val3 = (((Object)(object)_shader != (Object)null) ? new Material(_shader) : new Material(((Renderer)val2).sharedMaterial));
			val3.color = color;
			((Renderer)val2).material = val3;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			return val;
		}

		private static Mesh BuildArrowMesh()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = new Mesh
			{
				name = "BonkCoop_Arrow"
			};
			val.vertices = Il2CppStructArray<Vector3>.op_Implicit((Vector3[])(object)new Vector3[4]
			{
				new Vector3(0f, 0f, 1f),
				new Vector3(0.7f, 0f, -0.8f),
				new Vector3(0f, 0f, -0.35f),
				new Vector3(-0.7f, 0f, -0.8f)
			});
			val.triangles = Il2CppStructArray<int>.op_Implicit(new int[12]
			{
				0, 1, 2, 0, 2, 3, 0, 2, 1, 0,
				3, 2
			});
			val.RecalculateNormals();
			val.RecalculateBounds();
			return val;
		}

		private static void Remove(ulong id)
		{
			if (!_markers.TryGetValue(id, out var value))
			{
				return;
			}
			try
			{
				if ((Object)(object)value.ArrowTarget != (Object)null && (Object)(object)_cam != (Object)null)
				{
					_cam.RemoveArrow(value.ArrowTarget);
				}
			}
			catch
			{
			}
			if ((Object)(object)value.Root != (Object)null)
			{
				Object.Destroy((Object)(object)value.Root);
			}
			_markers.Remove(id);
		}

		public static void Clear()
		{
			if (_markers.Count == 0)
			{
				return;
			}
			foreach (ulong item in new List<ulong>(_markers.Keys))
			{
				Remove(item);
			}
			_cam = null;
		}
	}
	public static class MultiplayerScreen
	{
		private static GameObject _root;

		private static RectTransform _content;

		private static MainMenu _menu;

		private static string _shownKey;

		private static List<SteamLobby.FriendLobby> _friendLobbies = new List<SteamLobby.FriendLobby>();

		private static float _nextFriendScan;

		private static bool _open;

		private static float _pickStarted;

		private static readonly Color Red = new Color(1f, 0.35f, 0.3f, 1f);

		private static readonly Color Green = new Color(0.45f, 0.95f, 0.45f, 1f);

		private static readonly Color Gold = new Color(1f, 0.85f, 0.3f, 1f);

		private static readonly Color Grey = new Color(0.7f, 0.7f, 0.7f, 1f);

		private static readonly List<GameObject> _hiddenArrows = new List<GameObject>();

		private const float LeftX = 40f;

		private const float LeftTop = -340f;

		private const float BtnW = 300f;

		private const float BtnH = 72f;

		private const float BtnGap = 86f;

		private const float PanelX = 1400f;

		private const float PanelY = -250f;

		private const float PanelW = 480f;

		private const float PanelH = 580f;

		public static bool IsOpen
		{
			get
			{
				if (_open)
				{
					return (Object)(object)_root != (Object)null;
				}
				return false;
			}
		}

		public static bool PickingCharacter { get; private set; }

		public static bool PickingMap { get; private set; }

		public static void Open(MainMenu menu)
		{
			_menu = menu;
			EnsureRoot();
			_open = true;
			PickingCharacter = false;
			PickingMap = false;
			SetMenuHidden(hidden: true);
			HideSelectionArrows(hide: true);
			_root.SetActive(true);
			EnsureEventSystem();
			CameraToCharacters(close: true);
			_shownKey = null;
			_nextFriendScan = 0f;
		}

		public static void Close()
		{
			_open = false;
			PickingCharacter = false;
			PickingMap = false;
			LobbyLineup.Hide();
			CameraToCharacters(close: false);
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
			SetMenuHidden(hidden: false);
			HideSelectionArrows(hide: false);
		}

		private static void StartCharacterPick()
		{
			if (!((Object)(object)_menu == (Object)null))
			{
				PickingCharacter = true;
				_pickStarted = Time.unscaledTime;
				SteamLobby.SetPicking(picking: true);
				LobbyLineup.Hide();
				_root.SetActive(false);
				HideSelectionArrows(hide: false);
				_menu.GoToCharacterSelection();
			}
		}

		private static void StartMapPick()
		{
			if (!((Object)(object)_menu == (Object)null))
			{
				PickingMap = true;
				_pickStarted = Time.unscaledTime;
				LobbyLineup.Hide();
				_root.SetActive(false);
				HideSelectionArrows(hide: false);
				_menu.GoToMapSelection();
			}
		}

		public static void CloseForRun()
		{
			MultiplayerMenu.SuppressAutoOpen = true;
			PickingMap = false;
			PickingCharacter = false;
			_open = false;
			LobbyLineup.Hide();
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
			SetMenuHidden(hidden: false);
			HideSelectionArrows(hide: false);
		}

		public static void OnCharacterPicked(string character, string skin)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Picked ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(character);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (skin ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(skin);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") for the lobby");
			}
			log.LogInfo(val);
			SteamLobby.SetCharacter(character, skin);
			ReturnFromPick();
		}

		private static void ReturnFromPick()
		{
			if (PickingCharacter)
			{
				SteamLobby.SetPicking(picking: false);
			}
			PickingCharacter = false;
			PickingMap = false;
			if ((Object)(object)_menu != (Object)null)
			{
				_menu.GoToMenu();
			}
			SetMenuHidden(hidden: true);
			HideSelectionArrows(hide: true);
			_root.SetActive(true);
			CameraToCharacters(close: true);
			_shownKey = null;
		}

		private static void CameraToCharacters(bool close)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			try
			{
				MenuCamera val = (((Object)(object)_menu != (Object)null) ? _menu.menuCamera : null);
				if (!((Object)(object)val == (Object)null))
				{
					if (close)
					{
						val.GoToCharacters();
					}
					else
					{
						val.GoToMain();
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(20, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Camera move failed: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val2);
			}
		}

		public static string StatusText(SteamLobby.Member m, out Color color)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (m.Picking)
			{
				color = Grey;
				return "Choosing character";
			}
			if (m.Ready)
			{
				color = Green;
				return "Ready";
			}
			color = Grey;
			return "In menu";
		}

		private static void CheckPickCancelled()
		{
			if (!(Time.unscaledTime - _pickStarted < 0.75f) && !((Object)(object)_menu == (Object)null))
			{
				GameObject currentTab = _menu.currentTab;
				GameObject val = (PickingMap ? _menu.tabMaps : _menu.tabCharacters);
				if (!((Object)(object)currentTab != (Object)null) || !((Object)(object)val != (Object)null) || !(((Il2CppObjectBase)currentTab).Pointer == ((Il2CppObjectBase)val).Pointer))
				{
					ReturnFromPick();
				}
			}
		}

		private static void HideSelectionArrows(bool hide)
		{
			if (hide)
			{
				foreach (SelectionArrow item in Object.FindObjectsOfType<SelectionArrow>())
				{
					if (!((Object)(object)item == (Object)null) && ((Component)item).gameObject.activeSelf)
					{
						((Component)item).gameObject.SetActive(false);
						_hiddenArrows.Add(((Component)item).gameObject);
					}
				}
				return;
			}
			foreach (GameObject hiddenArrow in _hiddenArrows)
			{
				if ((Object)(object)hiddenArrow != (Object)null)
				{
					hiddenArrow.SetActive(true);
				}
			}
			_hiddenArrows.Clear();
		}

		private static void SetMenuHidden(bool hidden)
		{
			if (!((Object)(object)_menu == (Object)null) && !((Object)(object)_menu.tabMenu == (Object)null))
			{
				GameObject tabMenu = _menu.tabMenu;
				CanvasGroup val = tabMenu.GetComponent<CanvasGroup>();
				if ((Object)(object)val == (Object)null)
				{
					val = tabMenu.AddComponent<CanvasGroup>();
				}
				val.alpha = (hidden ? 0f : 1f);
				val.interactable = !hidden;
				val.blocksRaycasts = !hidden;
			}
		}

		private static void EnsureEventSystem()
		{
			//IL_0013: 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)
			if (!((Object)(object)EventSystem.current != (Object)null))
			{
				GameObject val = new GameObject("BonkCoop_EventSystem");
				val.AddComponent<EventSystem>();
				val.AddComponent<StandaloneInputModule>();
				Plugin.Log.LogInfo((object)"No EventSystem found, created one");
			}
		}

		public static void LateTick()
		{
			if (IsOpen && !PickingCharacter && !PickingMap)
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
			}
		}

		private static void EnsureRoot()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root != (Object)null))
			{
				_root = new GameObject("BonkCoop_MultiplayerScreen");
				Canvas obj = _root.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 50;
				CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 0.5f;
				_root.AddComponent<GraphicRaycaster>();
				RectTransform component = _root.GetComponent<RectTransform>();
				_content = UiKit.MakeRect("Content", (Transform)(object)component, 0f, 0f, 1920f, 1080f);
				_content.anchorMin = Vector2.zero;
				_content.anchorMax = Vector2.one;
				RectTransform content = _content;
				Vector2 offsetMin = (_content.offsetMax = Vector2.zero);
				content.offsetMin = offsetMin;
			}
		}

		public static void Tick()
		{
			if (!IsOpen)
			{
				return;
			}
			if (PickingCharacter || PickingMap)
			{
				CheckPickCancelled();
				return;
			}
			if (Input.GetKeyDown((KeyCode)27) && SteamLobby.State == SteamLobby.LobbyState.None)
			{
				Close();
				return;
			}
			if (SteamLobby.State == SteamLobby.LobbyState.None && Time.unscaledTime >= _nextFriendScan)
			{
				_nextFriendScan = Time.unscaledTime + 2f;
				try
				{
					_friendLobbies = SteamLobby.FindFriendLobbies();
				}
				catch (Exception ex)
				{
					LogOnce.Warn("Friend scan failed: " + ex.Message);
				}
			}
			string text = StateKey();
			if (text != _shownKey)
			{
				_shownKey = text;
				Rebuild();
				SelectFirstButton();
			}
			if (SteamLobby.InLobby)
			{
				LobbyLineup.Tick(_root.GetComponent<RectTransform>(), _root.GetComponent<Canvas>());
			}
			else
			{
				LobbyLineup.Hide();
			}
		}

		private static void SelectFirstButton()
		{
			EventSystem current = EventSystem.current;
			if (!((Object)(object)current == (Object)null))
			{
				current.SetSelectedGameObject((GameObject)null);
			}
		}

		private static string StateKey()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(SteamLobby.State).Append('|').Append(SteamLobby.Error)
				.Append('|')
				.Append(SteamLobby.IsHost);
			foreach (SteamLobby.Member member in SteamLobby.Members)
			{
				stringBuilder.Append('|').Append(member.Id).Append(member.Name)
					.Append(member.Ready)
					.Append(member.Character)
					.Append(member.Picking);
			}
			if (SteamLobby.State == SteamLobby.LobbyState.None)
			{
				foreach (SteamLobby.FriendLobby friendLobby in _friendLobbies)
				{
					stringBuilder.Append('#').Append(friendLobby.LobbyId).Append(friendLobby.FriendName);
				}
			}
			return stringBuilder.ToString();
		}

		private static void Rebuild()
		{
			for (int num = ((Transform)_content).childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)((Transform)_content).GetChild(num)).gameObject);
			}
			switch (SteamLobby.State)
			{
			case SteamLobby.LobbyState.None:
				BuildChoose();
				break;
			case SteamLobby.LobbyState.Creating:
			case SteamLobby.LobbyState.Joining:
				BuildChoose();
				break;
			case SteamLobby.LobbyState.InLobby:
				BuildLobby();
				break;
			}
		}

		private static void LeftTitle(string text)
		{
			UiKit.MakeLabel((Transform)(object)_content, text, 40f, -240f, 520f, 70f, 54f, (TextAlignmentOptions)513);
		}

		private static Button LeftButton(int index, string text, Action onClick, bool enabled = true)
		{
			return UiKit.MakeButton((Transform)(object)_content, text, 40f, -340f - (float)index * 86f, 300f, 72f, onClick, 34f, enabled);
		}

		private static RectTransform RightPanel(string title)
		{
			RectTransform rectTransform = ((Graphic)UiKit.MakePanel((Transform)(object)_content, 1400f, -250f, 480f, 580f)).rectTransform;
			UiKit.MakeLabel((Transform)(object)rectTransform, title, 20f, -14f, 440f, 60f, 40f, (TextAlignmentOptions)514);
			return rectTransform;
		}

		private static void ErrorLine(RectTransform panel, float y)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(SteamLobby.Error))
			{
				UiKit.MakeLabel((Transform)(object)panel, SteamLobby.Error, 20f, y, 440f, 70f, 22f, (TextAlignmentOptions)514, Red);
			}
		}

		private static void BuildChoose()
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			bool flag = SteamLobby.State == SteamLobby.LobbyState.Creating;
			bool flag2 = SteamLobby.State == SteamLobby.LobbyState.Joining;
			bool flag3 = flag || flag2;
			LeftTitle("Multiplayer");
			LeftButton(0, flag ? "Creating lobby..." : "Host game", SteamLobby.Host, !flag3);
			LeftButton(1, flag3 ? "Cancel" : "Back", flag3 ? new Action(SteamLobby.Leave) : new Action(Close));
			RectTransform val = RightPanel(flag2 ? "Joining lobby..." : "Join a friend");
			float num = -90f;
			if (_friendLobbies.Count == 0)
			{
				UiKit.MakeLabel((Transform)(object)val, "No friends hosting right now.\nAsk a friend to host, then invite you through Steam.", 24f, num, 432f, 110f, 24f, (TextAlignmentOptions)514, Grey);
			}
			else
			{
				foreach (SteamLobby.FriendLobby friendLobby in _friendLobbies)
				{
					if (num < -420f)
					{
						break;
					}
					ulong lobby = friendLobby.LobbyId;
					UiKit.MakeLabel((Transform)(object)val, friendLobby.FriendName, 28f, num - 6f, 270f, 50f, 30f, (TextAlignmentOptions)513);
					UiKit.MakeButton((Transform)(object)val, "Join", 310f, num, 140f, 56f, delegate
					{
						SteamLobby.Join(lobby);
					}, 28f);
					num -= 70f;
				}
			}
			UiKit.MakeButton((Transform)(object)val, "Join lobby code from clipboard", 24f, -490f, 432f, 58f, JoinFromClipboard, 24f);
			ErrorLine(val, -410f);
		}

		private static void BuildWaiting(string text)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			LeftTitle("Multiplayer");
			LeftButton(0, "Cancel", SteamLobby.Leave);
			UiKit.MakeLabel((Transform)(object)RightPanel("Please wait"), text, 20f, -120f, 440f, 60f, 32f, (TextAlignmentOptions)514, Grey);
		}

		private static void BuildLobby()
		{
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: 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_032f: Unknown result type (might be due to invalid IL or missing references)
			LeftTitle(SteamLobby.IsHost ? "Hosting" : "In lobby");
			bool myReady = SteamLobby.MyReady;
			bool flag = SteamLobby.MyCharacter.Length > 0;
			LeftButton(0, flag ? "Change character" : "Select character", StartCharacterPick, !myReady);
			LeftButton(1, myReady ? "Not ready" : (flag ? "Ready" : "Ready (pick a character)"), delegate
			{
				SteamLobby.SetReady(!SteamLobby.MyReady);
			}, flag);
			if (SteamLobby.IsHost)
			{
				bool flag2 = true;
				foreach (SteamLobby.Member member in SteamLobby.Members)
				{
					if (!member.IsMe && !member.Ready)
					{
						flag2 = false;
					}
				}
				bool enabled = flag && flag2;
				string text = ((!flag) ? "Start (pick a character)" : ((!flag2) ? "Start (waiting for players)" : "Start"));
				LeftButton(2, text, StartMapPick, enabled);
			}
			else
			{
				UiKit.MakeLabel((Transform)(object)_content, myReady ? "Waiting for the host to start..." : "Click Ready when you're set", 40f, -608f, 520f, 40f, 26f, (TextAlignmentOptions)513, Grey);
			}
			LeftButton(SteamLobby.IsHost ? 3 : 2, "Leave lobby", SteamLobby.Leave);
			string text2 = "";
			foreach (SteamLobby.Member member2 in SteamLobby.Members)
			{
				if (member2.IsOwner)
				{
					text2 = member2.Name;
				}
			}
			RectTransform val = RightPanel(text2 + "'s Lobby");
			float num = -86f;
			foreach (SteamLobby.Member member3 in SteamLobby.Members)
			{
				UiKit.MakeLabel((Transform)(object)val, member3.Name + (member3.IsMe ? "  (you)" : ""), 28f, num, 300f, 38f, 30f, (TextAlignmentOptions)513);
				if (member3.IsOwner)
				{
					UiKit.MakeLabel((Transform)(object)val, "HOST", 350f, num, 100f, 38f, 24f, (TextAlignmentOptions)516, Gold);
				}
				UiKit.MakeLabel((Transform)(object)val, (member3.Character.Length > 0) ? member3.Character : "No character yet", 28f, num - 34f, 220f, 28f, 22f, (TextAlignmentOptions)513, Grey);
				Color color;
				string text3 = StatusText(member3, out color);
				UiKit.MakeLabel((Transform)(object)val, text3, 230f, num - 34f, 220f, 28f, 22f, (TextAlignmentOptions)516, color);
				num -= 76f;
			}
			for (int num2 = SteamLobby.Members.Count; num2 < 4; num2++)
			{
				UiKit.MakeLabel((Transform)(object)val, "Empty slot", 28f, num, 260f, 40f, 26f, (TextAlignmentOptions)513, (Color?)new Color(1f, 1f, 1f, 0.3f));
				num -= 76f;
			}
			UiKit.MakeButton((Transform)(object)val, "Invite friends", 24f, -420f, 432f, 58f, SteamLobby.OpenInviteDialog, 26f);
			UiKit.MakeButton((Transform)(object)val, "Copy lobby code", 24f, -490f, 432f, 58f, CopyLobbyCode, 24f);
			ErrorLine(val, -340f);
		}

		private static void CopyLobbyCode()
		{
			GUIUtility.systemCopyBuffer = SteamLobby.LobbyId.ToString();
			SteamLobby.Error = "";
			Plugin.Log.LogInfo((object)"Lobby code copied");
		}

		private static void JoinFromClipboard()
		{
			if (ulong.TryParse((GUIUtility.systemCopyBuffer ?? "").Trim(), out var result))
			{
				SteamLobby.Join(result);
				return;
			}
			SteamLobby.Error = "Clipboard doesn't contain a lobby code.";
			_shownKey = null;
		}
	}
	public static class PartyHud
	{
		private class Frame
		{
			public GameObject Root;

			public RawImage Icon;

			public TextMeshProUGUI Name;

			public RectTransform HpFill;

			public TextMeshProUGUI HpText;

			public string Character;
		}

		private struct Entry
		{
			public string Name;

			public string Character;

			public int Hp;

			public int MaxHp;

			public bool IsMe;

			public bool Downed;

			public bool Connecting;

			public ulong Id;
		}

		private static GameObject _canvas;

		private static RectTransform _framesRoot;

		private static RectTransform _pauseRoot;

		private static readonly List<Frame> _frames = new List<Frame>();

		private static readonly List<Frame> _pauseRows = new List<Frame>();

		private static PauseUi _pauseUi;

		private static float _nextPauseLookup;

		private static float _nextRefresh;

		private const float FrameW = 300f;

		private const float FrameH = 64f;

		private const float IconSize = 56f;

		private const float BarW = 220f;

		private const float BarH = 16f;

		private static readonly Color HpRed = new Color(0.86f, 0.05f, 0.05f, 1f);

		private static readonly Color HpBack = new Color(0f, 0f, 0f, 0.55f);

		public static string CenterText;

		public static string CountdownText;

		private static TextMeshProUGUI _center;

		private static TextMeshProUGUI _notice;

		private static TextMeshProUGUI _countdown;

		private static float _noticeUntil;

		private static List<Entry> _others = new List<Entry>();

		public static void Notice(string text)
		{
			EnsureCanvas();
			((TMP_Text)_notice).text = text;
			_noticeUntil = Time.unscaledTime + 3.5f;
		}

		private static List<Entry> Teammates()
		{
			List<Entry> list = new List<Entry>();
			Dictionary<ulong, RemotePlayer> dictionary = new Dictionary<ulong, RemotePlayer>();
			foreach (RemotePlayer remote in CoopManager.Remotes)
			{
				dictionary[remote.PeerId] = remote;
			}
			if (SteamLobby.InLobby)
			{
				foreach (SteamLobby.Member member in SteamLobby.Members)
				{
					if (!member.IsMe)
					{
						if (dictionary.TryGetValue(member.Id, out var value))
						{
							list.Add(new Entry
							{
								Name = member.Name,
								Character = member.Character,
								Hp = value.Hp,
								MaxHp = value.MaxHp,
								Downed = value.Downed,
								Id = member.Id
							});
						}
						else
						{
							list.Add(new Entry
							{
								Name = member.Name,
								Character = member.Character,
								Connecting = true,
								Id = member.Id
							});
						}
					}
				}
			}
			else
			{
				foreach (RemotePlayer value2 in dictionary.Values)
				{
					list.Add(new Entry
					{
						Name = value2.DisplayName,
						Character = value2.Character,
						Hp = value2.Hp,
						MaxHp = value2.MaxHp,
						Downed = value2.Downed,
						Id = value2.PeerId
					});
				}
			}
			return list;
		}

		public static void Tick(MyPlayer player)
		{
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)player != (Object)null;
			bool flag2 = Time.unscaledTime >= _nextRefresh;
			if (flag2)
			{
				_nextRefresh = Time.unscaledTime + 0.1f;
				_others = (flag ? Teammates() : new List<Entry>());
			}
			List<Entry> others = _others;
			bool flag3 = (Object)(object)_notice != (Object)null && Time.unscaledTime < _noticeUntil;
			bool flag4 = !string.IsNullOrEmpty(CountdownText);
			if (!flag || (others.Count == 0 && !flag3 && !flag4 && string.IsNullOrEmpty(CenterText)))
			{
				if ((Object)(object)_canvas != (Object)null)
				{
					_canvas.SetActive(false);
				}
				CenterText = null;
				return;
			}
			EnsureCanvas();
			_canvas.SetActive(true);
			((Component)_notice).gameObject.SetActive(flag3);
			((Component)_countdown).gameObject.SetActive(flag4);
			if (flag4)
			{
				((TMP_Text)_countdown).text = CountdownText;
			}
			((Component)_center).gameObject.SetActive(!string.IsNullOrEmpty(CenterText));
			if (!string.IsNullOrEmpty(CenterText))
			{
				((TMP_Text)_center).text = CenterText;
			}
			bool flag5 = IsPaused();
			bool flag6 = false;
			try
			{
				flag6 = MyTime.paused && !flag5;
			}
			catch
			{
			}
			((Component)_pauseRoot).gameObject.SetActive(flag5);
			((Component)_framesRoot).gameObject.SetActive(!flag5 && !flag6);
			if (!flag2)
			{
				return;
			}
			SyncFrames(_frames, _framesRoot, others.Count, 0f, -74f, compact: true);
			for (int i = 0; i < others.Count; i++)
			{
				Fill(_frames[i], others[i]);
			}
			if (flag5)
			{
				List<Entry> list = new List<Entry>();
				list.Add(MyEntry(player));
				list.AddRange(others);
				RectTransform pauseRoot = _pauseRoot;
				pauseRoot.sizeDelta = new Vector2(360f, 80f + (float)list.Count * 76f);
				SyncFrames(_pauseRows, pauseRoot, list.Count, -64f, -76f, compact: false);
				for (int j = 0; j < list.Count; j++)
				{
					Fill(_pauseRows[j], list[j]);
				}
			}
		}

		private static Entry MyEntry(MyPlayer player)
		{
			int hp = 0;
			int maxHp = 0;
			try
			{
				PlayerHealth val = ((player.inventory != null) ? player.inventory.playerHealth : null);
				if (val != null)
				{
					hp = val.hp;
					maxHp = val.maxHp;
				}
			}
			catch
			{
			}
			string text = (SteamLobby.InLobby ? SteamLobby.NameOf(SteamLobby.MyId) : "You");
			return new Entry
			{
				Name = text + " (you)",
				Character = SteamLobby.MyCharacter,
				Hp = hp,
				MaxHp = maxHp,
				IsMe = true,
				Downed = DownedSync.Downed
			};
		}

		private static bool IsPaused()
		{
			if ((Object)(object)_pauseUi == (Object)null && Time.unscaledTime >= _nextPauseLookup)
			{
				_nextPauseLookup = Time.unscaledTime + 1f;
				_pauseUi = Object.FindObjectOfType<PauseUi>();
			}
			try
			{
				if ((Object)(object)_pauseUi == (Object)null)
				{
					return false;
				}
				GameObject main = _pauseUi.main;
				return _pauseUi.IsPaused() || ((Object)(object)main != (Object)null && main.activeInHierarchy);
			}
			catch
			{
				return false;
			}
		}

		private static void EnsureCanvas()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: 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_0236: 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_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: 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_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvas != (Object)null))
			{
				_canvas = new GameObject("BonkCoop_PartyHud");
				Object.DontDestroyOnLoad((Object)(object)_canvas);
				Canvas obj = _canvas.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 60;
				CanvasScaler obj2 = _canvas.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 0.5f;
				RectTransform component = _canvas.GetComponent<RectTransform>();
				_framesRoot = UiKit.MakeRect("Frames", (Transform)(object)component, 0f, -345f, 300f, 400f);
				RectTransform framesRoot = _framesRoot;
				RectTransform framesRoot2 = _framesRoot;
				RectTransform framesRoot3 = _framesRoot;
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(1f, 1f);
				framesRoot3.pivot = val;
				Vector2 anchorMin = (framesRoot2.anchorMax = val);
				framesRoot.anchorMin = anchorMin;
				_framesRoot.anchoredPosition = new Vector2(-30f, -395f);
				Image obj3 = UiKit.MakePanel((Transform)(object)component, 60f, -530f, 360f, 200f);
				_pauseRoot = ((Graphic)obj3).rectTransform;
				((Graphic)obj3).raycastTarget = false;
				UiKit.MakeLabel((Transform)(object)_pauseRoot, "Players", 20f, -10f, 300f, 46f, 34f, (TextAlignmentOptions)513);
				_center = UiKit.MakeLabel((Transform)(object)component, "", 0f, 0f, 1000f, 120f, 40f, (TextAlignmentOptions)514);
				RectTransform rectTransform = ((TMP_Text)_center).rectTransform;
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				rectTransform.pivot = val;
				anchorMin = (rectTransform.anchorMax = val);
				rectTransform.anchorMin = anchorMin;
				rectTransform.anchoredPosition = new Vector2(0f, -170f);
				_countdown = UiKit.MakeLabel((Transform)(object)component, "", 0f, 0f, 1100f, 130f, 52f, (TextAlignmentOptions)514, (Color?)new Color(0.55f, 0.85f, 1f));
				RectTransform rectTransform2 = ((TMP_Text)_countdown).rectTransform;
				((Vector2)(ref val))..ctor(0.5f, 1f);
				rectTransform2.pivot = val;
				anchorMin = (rectTransform2.anchorMax = val);
				rectTransform2.anchorMin = anchorMin;
				rectTransform2.anchoredPosition = new Vector2(0f, -190f);
				_notice = UiKit.MakeLabel((Transform)(object)component, "", 0f, 0f, 1000f, 60f, 34f, (TextAlignmentOptions)514, (Color?)new Color(1f, 0.85f, 0.3f));
				RectTransform rectTransform3 = ((TMP_Text)_notice).rectTransform;
				((Vector2)(ref val))..ctor(0.5f, 1f);
				rectTransform3.pivot = val;
				anchorMin = (rectTransform3.anchorMax = val);
				rectTransform3.anchorMin = anchorMin;
				rectTransform3.anchoredPosition = new Vector2(0f, -140f);
			}
		}

		private static void SyncFrames(List<Frame> list, RectTransform parent, int count, float startY, float step, bool compact)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			while (list.Count < count)
			{
				list.Add(MakeFrame(pare