Decompiled source of How To ROUNDS v0.17.6

BepInEx/plugins/HowToRounds/HowToRounds.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HowToRounds")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.17.6.0")]
[assembly: AssemblyInformationalVersion("0.17.6")]
[assembly: AssemblyProduct("HowToRounds")]
[assembly: AssemblyTitle("HowToRounds")]
[assembly: AssemblyVersion("0.17.6.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HowToRoundsMod
{
	internal sealed class AmmoHud : MonoBehaviour
	{
		private GameObject _canvasObject;

		private TextMeshProUGUI _ammoText;

		private TextMeshProUGUI _reloadText;

		private Image _reloadFill;

		private void Update()
		{
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			if (!RoundUpgradeEffects.ModeActive || RoundUpgradeEffects.LocalEliminated)
			{
				SetVisible(visible: false);
				return;
			}
			Player localPlayer = Player.LocalPlayer;
			Weapon val = (((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Holding != (Object)null && (Object)(object)localPlayer.Holding.HeldItem != (Object)null) ? localPlayer.Holding.HeldItem.Weapon : null);
			if ((Object)(object)val == (Object)null || ((Object)val).name.IndexOf("pistol", StringComparison.OrdinalIgnoreCase) < 0)
			{
				SetVisible(visible: false);
				return;
			}
			EnsureUi();
			SetVisible(visible: true);
			int num = (((Object)(object)val.Attachments != (Object)null) ? val.Attachments.AmmoPerMag : 0);
			((TMP_Text)_ammoText).text = val.Ammo + " / " + num;
			bool flag = (bool)(AccessTools.Field(typeof(Weapon), "_isReloading")?.GetValue(val) ?? ((object)false));
			float num2 = (flag ? GetReloadProgress(val) : 0f);
			_reloadFill.fillAmount = num2;
			((TMP_Text)_reloadText).text = (flag ? ("RELOADING  " + Mathf.RoundToInt(num2 * 100f) + "%") : "READY");
			((Graphic)_reloadText).color = (flag ? new Color(0.2f, 0.85f, 1f) : new Color(0.78f, 0.84f, 0.92f));
		}

		private static float GetReloadProgress(Weapon weapon)
		{
			try
			{
				object obj = AccessTools.Field(typeof(Tool), "_anim")?.GetValue(weapon);
				string text = AccessTools.Field(typeof(Weapon), "_activeReloadAnimName")?.GetValue(weapon) as string;
				if (obj == null || string.IsNullOrEmpty(text))
				{
					return 0f;
				}
				object obj2 = obj.GetType().GetProperty("Item")?.GetValue(obj, new object[1] { text });
				if (obj2 == null)
				{
					return 0f;
				}
				object obj3 = obj2.GetType().GetProperty("normalizedTime")?.GetValue(obj2, null);
				return (obj3 != null) ? Mathf.Clamp01(Convert.ToSingle(obj3)) : 0f;
			}
			catch
			{
				return 0f;
			}
		}

		private void EnsureUi()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_00fc: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: 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_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: 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_02ce: Expected O, but got Unknown
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvasObject != (Object)null))
			{
				TMP_Text val = Object.FindObjectOfType<TMP_Text>();
				TMP_FontAsset font = (((Object)(object)val != (Object)null) ? val.font : null);
				_canvasObject = new GameObject("HowToRounds_AmmoHud", new Type[1] { typeof(RectTransform) });
				_canvasObject.transform.SetParent(((Component)this).transform, false);
				Canvas obj = _canvasObject.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 32060;
				CanvasScaler obj2 = _canvasObject.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				GameObject val2 = new GameObject("Panel", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent(_canvasObject.transform, false);
				RectTransform component = val2.GetComponent<RectTransform>();
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(1f, 0f);
				component.pivot = val3;
				Vector2 val4 = (component.anchorMin = (component.anchorMax = val3));
				component.anchoredPosition = new Vector2(-32f, 42f);
				component.sizeDelta = new Vector2(270f, 118f);
				((Graphic)val2.AddComponent<Image>()).color = new Color(0.1f, 0.17f, 0.29f, 0.94f);
				Outline obj3 = val2.AddComponent<Outline>();
				((Shadow)obj3).effectColor = new Color(0.92f, 0.95f, 1f, 0.95f);
				((Shadow)obj3).effectDistance = new Vector2(2f, -2f);
				AddText((Transform)(object)component, "AMMO", 19f, new Color(0.7f, 0.78f, 0.89f), new Vector2(0f, 42f), new Vector2(240f, 28f), font, out var _);
				AddText((Transform)(object)component, "3 / 3", 38f, Color.white, new Vector2(0f, 10f), new Vector2(240f, 46f), font, out _ammoText);
				GameObject val7 = new GameObject("ReloadTrack", new Type[1] { typeof(RectTransform) });
				val7.transform.SetParent((Transform)(object)component, false);
				RectTransform component2 = val7.GetComponent<RectTransform>();
				((Vector2)(ref val4))..ctor(0.5f, 0.5f);
				component2.anchorMax = val4;
				component2.anchorMin = val4;
				component2.anchoredPosition = new Vector2(0f, -27f);
				component2.sizeDelta = new Vector2(226f, 11f);
				((Graphic)val7.AddComponent<Image>()).color = new Color(0.025f, 0.05f, 0.09f, 0.95f);
				GameObject val8 = new GameObject("Fill", new Type[1] { typeof(RectTransform) });
				val8.transform.SetParent((Transform)(object)component2, false);
				RectTransform component3 = val8.GetComponent<RectTransform>();
				component3.anchorMin = Vector2.zero;
				component3.anchorMax = Vector2.one;
				val4 = (component3.offsetMin = (component3.offsetMax = Vector2.zero));
				_reloadFill = val8.AddComponent<Image>();
				((Graphic)_reloadFill).color = new Color(0.12f, 0.78f, 1f, 1f);
				_reloadFill.type = (Type)3;
				_reloadFill.fillMethod = (FillMethod)0;
				_reloadFill.fillOrigin = 0;
				_reloadFill.fillAmount = 0f;
				AddText((Transform)(object)component, "READY", 16f, new Color(0.78f, 0.84f, 0.92f), new Vector2(0f, -46f), new Vector2(240f, 25f), font, out _reloadText);
			}
		}

		private static void AddText(Transform parent, string value, float size, Color color, Vector2 position, Vector2 dimensions, TMP_FontAsset font, out TextMeshProUGUI text)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(value, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			component.anchorMax = val2;
			component.anchorMin = val2;
			component.anchoredPosition = position;
			component.sizeDelta = dimensions;
			text = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)text).font = font;
			}
			((TMP_Text)text).text = value;
			((TMP_Text)text).fontSize = size;
			((Graphic)text).color = color;
			((TMP_Text)text).alignment = (TextAlignmentOptions)514;
			((Graphic)text).raycastTarget = false;
		}

		private void SetVisible(bool visible)
		{
			if ((Object)(object)_canvasObject != (Object)null && _canvasObject.activeSelf != visible)
			{
				_canvasObject.SetActive(visible);
			}
		}
	}
	internal sealed class ArenaRuntime
	{
		private static readonly Vector3 ArenaOrigin = new Vector3(0f, 750f, 0f);

		private readonly Plugin _plugin;

		private AssetBundle _bundle;

		private GameObject _arena;

		private Transform[] _spawns;

		private Collider _killVolume;

		private CSteamID _lobby;

		private Vector3 _localSpawnPosition;

		private float _localSpawnYaw;

		private float _killPlaneY;

		private bool _deploymentStarted;

		private bool _ready;

		private UpgradeDraft _draft;

		private readonly List<CSteamID> _members = new List<CSteamID>();

		private bool _isHost;

		private int _localSlot = -1;

		private string _roundId = string.Empty;

		private string _roundState = string.Empty;

		private bool _preparingRound;

		private bool _draftFinished;

		private bool _combatStarted;

		private bool _localEliminated;

		private int _lastAliveSlot = -1;

		private int _upgradeEpoch;

		private float _nextNetworkPoll;

		private float _nextVitalsRefresh;

		private float _roundOverAt;

		private RoundResultUi _resultUi;

		private MatchDecisionUi _matchUi;

		private SpectatorController _spectator;

		private string _arenaId = "arena03";

		private string _arenaName = "Arena03";

		private const string RoundIdKey = "htr_round_id";

		private const string RoundStateKey = "htr_round_state";

		private const string RoundNumberKey = "htr_round_number";

		private const string EligibleKey = "htr_round_eligible";

		private const string WinnerKey = "htr_round_winner";

		private const string UpgradeEpochKey = "htr_upgrade_epoch";

		private const int WinsPerMatch = 10;

		internal ArenaRuntime(Plugin plugin)
		{
			_plugin = plugin;
		}

		internal void Begin(CSteamID lobby)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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)
			_lobby = lobby;
			if (!_deploymentStarted)
			{
				_arenaId = NormalizeArenaId(SteamMatchmaking.GetLobbyData(lobby, "htr_arena"));
				_arenaName = DisplayName(_arenaId);
				_deploymentStarted = true;
				RoundUpgradeEffects.ModeActive = true;
				((MonoBehaviour)_plugin).StartCoroutine(DeployWhenPlayerExists());
			}
		}

		internal void Tick()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			_draft?.Tick();
			RoundUpgradeEffects.Tick();
			if (!_ready || (Object)(object)Player.LocalPlayer == (Object)null)
			{
				return;
			}
			if (_roundState == "combat")
			{
				CheckLocalElimination();
			}
			if (_draft != null && _draft.IsComplete && !_draftFinished)
			{
				_draftFinished = true;
				StartCombatLocally();
				if (_isHost)
				{
					SteamMatchmaking.SetLobbyData(_lobby, "htr_round_state", "combat");
				}
			}
			if (!(Time.unscaledTime < _nextNetworkPoll))
			{
				_nextNetworkPoll = Time.unscaledTime + 0.1f;
				RefreshRoundState();
				if (_isHost && Time.unscaledTime >= _nextVitalsRefresh)
				{
					_nextVitalsRefresh = Time.unscaledTime + 0.5f;
					RefillVitals(_roundState != "combat");
				}
				if (_isHost && _roundState == "combat")
				{
					EvaluateWinner();
				}
				if (_isHost && _roundState == "over" && Time.unscaledTime >= _roundOverAt + 3f)
				{
					BeginNextRound();
				}
			}
		}

		private IEnumerator DeployWhenPlayerExists()
		{
			Plugin.Log.LogInfo((object)("Waiting for the local player before loading " + _arenaName + "..."));
			while ((Object)(object)Player.LocalPlayer == (Object)null || !((Component)Player.LocalPlayer).gameObject.activeInHierarchy)
			{
				yield return (object)new WaitForSecondsRealtime(0.25f);
			}
			yield return (object)new WaitForSecondsRealtime(1.25f);
			if (!LoadArena(_arenaId))
			{
				yield break;
			}
			if (_spawns.Length == 0)
			{
				Plugin.Log.LogError((object)(_arenaName + " contains no HTR_Spawn_1-4 markers."));
				yield break;
			}
			int spawnIndex = UpdateLocalSpawn();
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				localPlayer.LocalTeleport(_localSpawnPosition, _localSpawnYaw, true);
			}
			yield return (object)new WaitForSecondsRealtime(0.45f);
			localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null && Vector3.Distance(GetPhysicalPosition(localPlayer), _localSpawnPosition) > 5f)
			{
				localPlayer.LocalTeleport(_localSpawnPosition, _localSpawnYaw, true);
			}
			if ((Object)(object)localPlayer != (Object)null)
			{
				yield return GrantStartingLoadout(localPlayer);
			}
			BuildMemberOrder();
			_isHost = SteamMatchmaking.GetLobbyOwner(_lobby) == SteamUser.GetSteamID();
			_localSlot = _members.IndexOf(SteamUser.GetSteamID());
			_ready = true;
			if (_isHost)
			{
				_upgradeEpoch = 0;
				SteamMatchmaking.SetLobbyData(_lobby, "htr_upgrade_epoch", "0");
				ResetScores();
				StartRound(1, AllEligible());
			}
			else
			{
				_upgradeEpoch = ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_upgrade_epoch"), 0);
			}
			Plugin.Log.LogInfo((object)(_arenaName + " ready. Local player assigned to spawn " + (spawnIndex + 1) + "."));
		}

		private IEnumerator GrantStartingLoadout(Player player)
		{
			float deadline = Time.unscaledTime + 8f;
			while (((Object)(object)Server.Instance == (Object)null || (Object)(object)player.Inventory == (Object)null || (Object)(object)player.Holding == (Object)null) && Time.unscaledTime < deadline)
			{
				yield return (object)new WaitForSecondsRealtime(0.1f);
			}
			if ((Object)(object)Server.Instance == (Object)null || (Object)(object)player.Inventory == (Object)null || (Object)(object)player.Holding == (Object)null)
			{
				Plugin.Log.LogError((object)"Could not grant the starting loadout because the player network objects were not ready.");
				yield break;
			}
			Item spawnable = GameInfo.GetSpawnable("knife");
			Item pistolPrefab = GameInfo.GetSpawnable("pistol");
			if ((Object)(object)spawnable == (Object)null || (Object)(object)pistolPrefab == (Object)null)
			{
				Plugin.Log.LogError((object)("Could not find the vanilla Knife or Pistol prefabs (knife=" + ((Object)(object)spawnable != (Object)null) + ", pistol=" + ((Object)(object)pistolPrefab != (Object)null) + ")."));
				yield break;
			}
			Vector3 itemPosition = _localSpawnPosition + Vector3.up;
			Item heldItem = player.Holding.HeldItem;
			Server.Instance.BuyItem(spawnable.ID, player, heldItem, itemPosition, Quaternion.identity, true);
			deadline = Time.unscaledTime + 5f;
			while (!IsKnife(player.Holding.HeldItem) && Time.unscaledTime < deadline)
			{
				yield return (object)new WaitForSecondsRealtime(0.1f);
			}
			Item heldItem2 = player.Holding.HeldItem;
			if (!IsKnife(heldItem2))
			{
				Plugin.Log.LogError((object)"The server did not equip the free starting Knife in time.");
				yield break;
			}
			Server.Instance.BuyItem(pistolPrefab.ID, player, heldItem2, itemPosition, Quaternion.identity, true);
			deadline = Time.unscaledTime + 5f;
			while (!IsPistol(player.Holding.HeldItem) && Time.unscaledTime < deadline)
			{
				yield return (object)new WaitForSecondsRealtime(0.1f);
			}
			if (!IsPistol(player.Holding.HeldItem))
			{
				Plugin.Log.LogError((object)"The server did not equip the free starting Pistol in time.");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Starting loadout granted: Pistol equipped and Knife stored in the inventory.");
			}
		}

		private static bool IsKnife(Item item)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)item.Melee != (Object)null)
			{
				return ((Object)item).name.IndexOf("knife", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static bool IsPistol(Item item)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)item.Weapon != (Object)null)
			{
				return ((Object)item).name.IndexOf("pistol", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private bool LoadArena(string requestedArenaId)
		{
			//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)
			string text = NormalizeArenaId(requestedArenaId);
			if ((Object)(object)_arena != (Object)null && (Object)(object)_bundle != (Object)null && text == _arenaId)
			{
				return true;
			}
			try
			{
				string text2 = Path.GetDirectoryName(((BaseUnityPlugin)_plugin).Info.Location);
				string path = "howtorounds_" + text;
				if (text2 == null)
				{
					text2 = string.Empty;
				}
				string text3 = Path.Combine(text2, path);
				if (!File.Exists(text3))
				{
					Plugin.Log.LogError((object)("Arena bundle was not found: " + text3));
					return false;
				}
				AssetBundle val = AssetBundle.LoadFromFile(text3);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)("Unity could not load the " + DisplayName(text) + " AssetBundle."));
					return false;
				}
				GameObject val2 = val.LoadAsset<GameObject>("assets/howtorounds/prefabs/" + text + ".prefab");
				if ((Object)(object)val2 == (Object)null)
				{
					string[] allAssetNames = val.GetAllAssetNames();
					foreach (string text4 in allAssetNames)
					{
						val2 = val.LoadAsset<GameObject>(text4);
						if ((Object)(object)val2 != (Object)null)
						{
							break;
						}
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogError((object)(DisplayName(text) + " prefab was not present in the AssetBundle."));
					val.Unload(true);
					return false;
				}
				GameObject val3 = Object.Instantiate<GameObject>(val2, ArenaOrigin, Quaternion.identity);
				if ((Object)(object)val3 == (Object)null)
				{
					Plugin.Log.LogError((object)(DisplayName(text) + " could not be instantiated."));
					val.Unload(true);
					return false;
				}
				GameObject arena = _arena;
				AssetBundle bundle = _bundle;
				_arenaId = text;
				_arenaName = DisplayName(text);
				_arena = val3;
				_bundle = val;
				((Object)_arena).name = "HowToRounds_" + _arenaName + "_Runtime";
				Object.DontDestroyOnLoad((Object)(object)_arena);
				ConfigureLevelSurfaces();
				ResolveArenaMarkers();
				if ((Object)(object)arena != (Object)null)
				{
					Object.Destroy((Object)(object)arena);
				}
				if ((Object)(object)bundle != (Object)null)
				{
					bundle.Unload(false);
				}
				Plugin.Log.LogInfo((object)("Loaded " + _arenaName + " for round " + CurrentRoundNumber() + "."));
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)(_arenaName + " loading failed: " + ex));
				return false;
			}
		}

		private void ConfigureLevelSurfaces()
		{
			//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_0079: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			LayerMask val = GameInfo.LevelLayer;
			int value = ((LayerMask)(ref val)).value;
			int num = FirstLayerInMask(value);
			if (num < 0)
			{
				Plugin.Log.LogWarning((object)"GameInfo.LevelLayer is empty; arena surfaces could not be marked as jumpable.");
				return;
			}
			int num2 = 0;
			Collider[] componentsInChildren = _arena.GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger)
				{
					GameObject gameObject = ((Component)val2).gameObject;
					gameObject.layer = num;
					try
					{
						gameObject.tag = "Level";
					}
					catch (UnityException ex)
					{
						UnityException ex2 = ex;
						Plugin.Log.LogWarning((object)("Could not tag arena surface as Level: " + ((Exception)(object)ex2).Message));
					}
					num2++;
				}
			}
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[9]
			{
				"Configured ",
				num2.ToString(),
				" arena colliders on Level layer ",
				num.ToString(),
				" (LevelMask=",
				value.ToString(),
				", CanJumpOnLayers=",
				null,
				null
			};
			val = GameInfo.CanJumpOnLayers;
			obj[7] = ((LayerMask)(ref val)).value.ToString();
			obj[8] = ").";
			log.LogInfo((object)string.Concat(obj));
		}

		private static int FirstLayerInMask(int mask)
		{
			for (int i = 0; i < 32; i++)
			{
				if ((mask & (1 << i)) != 0)
				{
					return i;
				}
			}
			return -1;
		}

		private void ResolveArenaMarkers()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			_killVolume = null;
			List<Transform> list = new List<Transform>(4);
			Transform[] componentsInChildren = _arena.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name.StartsWith("HTR_Spawn_", StringComparison.Ordinal))
				{
					list.Add(val);
				}
				else if (((Object)val).name == "HTR_KillVolume")
				{
					_killVolume = ((Component)val).GetComponent<Collider>();
				}
			}
			list.Sort((Transform left, Transform right) => string.CompareOrdinal(((Object)left).name, ((Object)right).name));
			_spawns = list.ToArray();
			if ((Object)(object)_killVolume != (Object)null)
			{
				Bounds bounds = _killVolume.bounds;
				_killPlaneY = ((Bounds)(ref bounds)).max.y;
			}
			else
			{
				_killPlaneY = ArenaOrigin.y - 20f;
				Plugin.Log.LogWarning((object)(_arenaName + " has no collider named HTR_KillVolume; only the fallback height check will work."));
			}
		}

		private int UpdateLocalSpawn()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			int num = ResolveLocalSpawnIndex(_spawns.Length);
			Transform val = _spawns[num];
			_localSpawnPosition = val.position + Vector3.up * 0.15f;
			_localSpawnYaw = val.eulerAngles.y;
			return num;
		}

		private static string NormalizeArenaId(string arenaId)
		{
			if (!TryNormalizeArenaId(arenaId, out var normalized))
			{
				return "arena03";
			}
			return normalized;
		}

		internal static string DisplayName(string arenaId)
		{
			string text = NormalizeArenaId(arenaId);
			return "Arena" + text.Substring(5);
		}

		private static bool TryNormalizeArenaId(string arenaId, out string normalized)
		{
			normalized = null;
			if (string.IsNullOrEmpty(arenaId))
			{
				return false;
			}
			string text = arenaId.Trim().ToLowerInvariant();
			if (!text.StartsWith("arena", StringComparison.Ordinal) || text.Length < 7)
			{
				return false;
			}
			for (int i = 5; i < text.Length; i++)
			{
				if (!char.IsDigit(text[i]))
				{
					return false;
				}
			}
			if (!int.TryParse(text.Substring(5), out var result) || result < 3)
			{
				return false;
			}
			normalized = "arena" + result.ToString("D2");
			return true;
		}

		internal static List<string> FindInstalledArenas(string pluginDirectory)
		{
			List<string> list = new List<string>();
			if (string.IsNullOrEmpty(pluginDirectory) || !Directory.Exists(pluginDirectory))
			{
				return list;
			}
			string[] files = Directory.GetFiles(pluginDirectory, "howtorounds_arena*");
			for (int i = 0; i < files.Length; i++)
			{
				if (TryNormalizeArenaId(Path.GetFileName(files[i]).Substring("howtorounds_".Length), out var normalized) && !list.Contains(normalized))
				{
					list.Add(normalized);
				}
			}
			list.Sort((string left, string right) => int.Parse(left.Substring(5)).CompareTo(int.Parse(right.Substring(5))));
			return list;
		}

		private int ResolveLocalSpawnIndex(int spawnCount)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_004c: 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)
			try
			{
				CSteamID steamID = SteamUser.GetSteamID();
				CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(_lobby);
				if (steamID == lobbyOwner)
				{
					return 0;
				}
				int num = 1;
				int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(_lobby);
				for (int i = 0; i < numLobbyMembers; i++)
				{
					CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(_lobby, i);
					if (!(lobbyMemberByIndex == lobbyOwner))
					{
						if (lobbyMemberByIndex == steamID)
						{
							return num % spawnCount;
						}
						num++;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not resolve the Steam spawn slot: " + ex.Message));
			}
			return 0;
		}

		private void BuildMemberOrder()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			_members.Clear();
			CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(_lobby);
			if (lobbyOwner.m_SteamID != 0L)
			{
				_members.Add(lobbyOwner);
			}
			int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(_lobby);
			for (int i = 0; i < numLobbyMembers; i++)
			{
				CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(_lobby, i);
				if (lobbyMemberByIndex != lobbyOwner)
				{
					_members.Add(lobbyMemberByIndex);
				}
			}
		}

		private bool[] AllEligible()
		{
			bool[] array = new bool[_members.Count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = true;
			}
			return array;
		}

		private void StartRound(int number, bool[] eligible)
		{
			//IL_0076: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			string text = (string.IsNullOrEmpty(_roundId) ? _arenaId : SelectArenaForNextRound());
			string text2 = text + ":" + number + "-" + SteamUtils.GetServerRealTime() + "-" + Random.Range(100, 999);
			SteamMatchmaking.SetLobbyData(_lobby, "htr_arena", text);
			SteamMatchmaking.SetLobbyData(_lobby, "htr_round_number", number.ToString());
			SteamMatchmaking.SetLobbyData(_lobby, "htr_round_eligible", EncodeEligible(eligible));
			SteamMatchmaking.SetLobbyData(_lobby, "htr_round_winner", "-1");
			SteamMatchmaking.SetLobbyData(_lobby, "htr_round_id", text2);
			SteamMatchmaking.SetLobbyData(_lobby, "htr_round_state", "draft");
			ObserveNewRound(text2, eligible);
		}

		private void RefreshRoundState()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			int num = ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_upgrade_epoch"), 0);
			if (num != _upgradeEpoch)
			{
				_upgradeEpoch = num;
				RoundUpgradeEffects.ResetAllUpgrades();
			}
			string lobbyData = SteamMatchmaking.GetLobbyData(_lobby, "htr_round_id");
			string lobbyData2 = SteamMatchmaking.GetLobbyData(_lobby, "htr_round_state");
			if (!string.IsNullOrEmpty(lobbyData) && lobbyData != _roundId)
			{
				ObserveNewRound(lobbyData, DecodeEligible(SteamMatchmaking.GetLobbyData(_lobby, "htr_round_eligible")));
			}
			if (!(lobbyData2 == _roundState))
			{
				_roundState = lobbyData2;
				switch (lobbyData2)
				{
				case "combat":
					StartCombatLocally();
					break;
				case "over":
					ShowRoundResult();
					break;
				case "match_over":
					ShowMatchResult();
					break;
				}
			}
		}

		private void ObserveNewRound(string id, bool[] eligible)
		{
			_roundId = id;
			_roundState = "draft";
			_draft = null;
			_draftFinished = false;
			_combatStarted = false;
			_localEliminated = false;
			_lastAliveSlot = -1;
			_preparingRound = true;
			RoundUpgradeEffects.LocalEliminated = false;
			StopSpectating();
			RoundUpgradeEffects.ResetProjectileTracking();
			if ((Object)(object)_resultUi != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_resultUi).gameObject);
			}
			if ((Object)(object)_matchUi != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_matchUi).gameObject);
			}
			string roundArenaId = ArenaIdFromRoundId(id);
			((MonoBehaviour)_plugin).StartCoroutine(PrepareRound(eligible, roundArenaId));
		}

		private IEnumerator PrepareRound(bool[] eligible, string roundArenaId)
		{
			Player local = Player.LocalPlayer;
			RoundUpgradeEffects.SelectionActive = true;
			RoundUpgradeEffects.AllowRoundRespawn = true;
			if ((Object)(object)local != (Object)null && (Object)(object)local.Rigidbody != (Object)null)
			{
				local.Rigidbody.linearVelocity = Vector3.zero;
				local.Rigidbody.constraints = (RigidbodyConstraints)126;
			}
			if (!LoadArena(roundArenaId))
			{
				RoundUpgradeEffects.AllowRoundRespawn = false;
				_preparingRound = false;
				yield break;
			}
			if (_spawns.Length == 0)
			{
				Plugin.Log.LogError((object)(_arenaName + " contains no HTR_Spawn_1-4 markers."));
				RoundUpgradeEffects.AllowRoundRespawn = false;
				_preparingRound = false;
				yield break;
			}
			UpdateLocalSpawn();
			if ((Object)(object)local != (Object)null && (Object)(object)local.Dying != (Object)null && local.Dying.IsDead && (Object)(object)Server.Instance != (Object)null)
			{
				Server.Instance.RespawnPlayer(local, _localSpawnPosition, Quaternion.Euler(0f, _localSpawnYaw, 0f));
				float deadline = Time.unscaledTime + 6f;
				while (local.Dying.IsDead && Time.unscaledTime < deadline)
				{
					yield return (object)new WaitForSecondsRealtime(0.1f);
				}
			}
			RoundUpgradeEffects.AllowRoundRespawn = false;
			local = Player.LocalPlayer;
			if ((Object)(object)local != (Object)null)
			{
				local.LocalTeleport(_localSpawnPosition, _localSpawnYaw, true);
				if ((Object)(object)local.Rigidbody != (Object)null)
				{
					local.Rigidbody.linearVelocity = Vector3.zero;
					local.Rigidbody.constraints = (RigidbodyConstraints)126;
				}
				if (!IsPistol(((Object)(object)local.Holding != (Object)null) ? local.Holding.HeldItem : null))
				{
					yield return GrantStartingLoadout(local);
				}
			}
			_draft = new UpgradeDraft(_lobby, eligible);
			_draft.Begin();
			_preparingRound = false;
			SteamMatchmaking.SetLobbyMemberData(_lobby, "htr_life", _roundId + ":alive");
		}

		private string SelectArenaForNextRound()
		{
			List<string> list = FindInstalledArenas(Path.GetDirectoryName(((BaseUnityPlugin)_plugin).Info.Location) ?? string.Empty);
			if (list.Count == 0)
			{
				return _arenaId;
			}
			if (list.Count == 1)
			{
				return list[0];
			}
			list.Remove(_arenaId);
			return list[Random.Range(0, list.Count)];
		}

		private string ArenaIdFromRoundId(string roundId)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			int num = (string.IsNullOrEmpty(roundId) ? (-1) : roundId.IndexOf(':'));
			if (num > 0)
			{
				return NormalizeArenaId(roundId.Substring(0, num));
			}
			return NormalizeArenaId(SteamMatchmaking.GetLobbyData(_lobby, "htr_arena"));
		}

		private void StartCombatLocally()
		{
			//IL_0079: 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)
			if (_combatStarted || _preparingRound)
			{
				return;
			}
			_combatStarted = true;
			_roundState = "combat";
			_localEliminated = false;
			RoundUpgradeEffects.SelectionActive = false;
			RoundUpgradeEffects.LocalEliminated = false;
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				localPlayer.LocalTeleport(_localSpawnPosition, _localSpawnYaw, true);
				if ((Object)(object)localPlayer.Rigidbody != (Object)null)
				{
					localPlayer.Rigidbody.constraints = (RigidbodyConstraints)112;
				}
			}
			RoundUpgradeEffects.RefillLocalPistol();
			SteamMatchmaking.SetLobbyMemberData(_lobby, "htr_life", _roundId + ":alive");
			if (_isHost)
			{
				RefillVitals(includeHealth: true);
			}
		}

		private void CheckLocalElimination()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0076: 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)
			if (_localEliminated)
			{
				return;
			}
			Player localPlayer = Player.LocalPlayer;
			bool flag = (Object)(object)localPlayer.Dying != (Object)null && localPlayer.Dying.IsDead;
			bool flag2 = GetPhysicalPosition(localPlayer).y < _killPlaneY;
			if (flag || flag2)
			{
				if (flag2 && !flag && (Object)(object)Server.Instance != (Object)null)
				{
					Vector3 physicalPosition = GetPhysicalPosition(localPlayer);
					Server.Instance.HitPlayer(localPlayer, 10000, Vector3.down * 10f, physicalPosition, (byte)0, (Player)null);
				}
				_localEliminated = true;
				RoundUpgradeEffects.LocalEliminated = true;
				BeginSpectating();
				SteamMatchmaking.SetLobbyMemberData(_lobby, "htr_life", _roundId + ":dead");
				if ((Object)(object)localPlayer.Rigidbody != (Object)null)
				{
					localPlayer.Rigidbody.linearVelocity = Vector3.zero;
					localPlayer.Rigidbody.constraints = (RigidbodyConstraints)126;
				}
				Plugin.Log.LogInfo((object)("Local player eliminated from round " + CurrentRoundNumber() + "."));
			}
		}

		private void EvaluateWinner()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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)
			int num = 0;
			int num2 = -1;
			for (int i = 0; i < _members.Count; i++)
			{
				if (!(SteamMatchmaking.GetLobbyMemberData(_lobby, _members[i], "htr_life") == _roundId + ":dead"))
				{
					num++;
					num2 = i;
				}
			}
			if (num == 1)
			{
				_lastAliveSlot = num2;
			}
			if (_members.Count >= 2 && num <= 1)
			{
				int num3 = ((num == 1) ? num2 : _lastAliveSlot);
				if (num3 < 0)
				{
					num3 = 0;
				}
				int num4 = GetWins(num3) + 1;
				SetWins(num3, num4);
				SteamMatchmaking.SetLobbyData(_lobby, "htr_round_winner", num3.ToString());
				string text = ((num4 >= 10) ? "match_over" : "over");
				SteamMatchmaking.SetLobbyData(_lobby, "htr_round_state", text);
				_roundState = text;
				_roundOverAt = Time.unscaledTime;
				if (text == "match_over")
				{
					ShowMatchResult();
				}
				else
				{
					ShowRoundResult();
				}
			}
		}

		private void ShowRoundResult()
		{
			//IL_0018: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			_roundOverAt = Time.unscaledTime;
			RoundUpgradeEffects.SelectionActive = true;
			StopSpectating();
			int num = ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_round_winner"), -1);
			string winner = ((num >= 0 && num < _members.Count) ? SteamFriends.GetFriendPersonaName(_members[num]) : "PLAYER");
			if (num >= 0 && num < _members.Count && _members[num] == SteamUser.GetSteamID())
			{
				winner = SteamFriends.GetPersonaName();
			}
			GameObject val = new GameObject("HowToRounds_RoundResult");
			Object.DontDestroyOnLoad((Object)(object)val);
			_resultUi = val.AddComponent<RoundResultUi>();
			_resultUi.Build(winner, CurrentRoundNumber(), GetWins(num), 10);
		}

		private void ShowMatchResult()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			RoundUpgradeEffects.SelectionActive = true;
			StopSpectating();
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Rigidbody != (Object)null)
			{
				localPlayer.Rigidbody.linearVelocity = Vector3.zero;
				localPlayer.Rigidbody.constraints = (RigidbodyConstraints)126;
			}
			if (!((Object)(object)_matchUi != (Object)null))
			{
				int slot = ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_round_winner"), -1);
				string winner = MemberName(slot);
				GameObject val = new GameObject("HowToRounds_MatchDecision");
				Object.DontDestroyOnLoad((Object)(object)val);
				_matchUi = val.AddComponent<MatchDecisionUi>();
				_matchUi.Build(winner, _isHost, ContinueMatch, RestartMatch);
			}
		}

		private void ContinueMatch()
		{
			if (_isHost && !(_roundState != "match_over"))
			{
				ResetScores();
				StartRound(CurrentRoundNumber() + 1, AllEligible());
			}
		}

		private void RestartMatch()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (_isHost && !(_roundState != "match_over"))
			{
				_upgradeEpoch++;
				SteamMatchmaking.SetLobbyData(_lobby, "htr_upgrade_epoch", _upgradeEpoch.ToString());
				RoundUpgradeEffects.ResetAllUpgrades();
				ResetScores();
				StartRound(1, AllEligible());
			}
		}

		private string MemberName(int slot)
		{
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			if (slot < 0 || slot >= _members.Count)
			{
				return "PLAYER";
			}
			if (_members[slot] == SteamUser.GetSteamID())
			{
				return SteamFriends.GetPersonaName();
			}
			string friendPersonaName = SteamFriends.GetFriendPersonaName(_members[slot]);
			if (!string.IsNullOrWhiteSpace(friendPersonaName) && !(friendPersonaName == "[unknown]"))
			{
				return friendPersonaName;
			}
			return "PLAYER " + (slot + 1);
		}

		private int GetWins(int slot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_wins_" + slot), 0);
		}

		private void SetWins(int slot, int wins)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SteamMatchmaking.SetLobbyData(_lobby, "htr_wins_" + slot, Mathf.Max(0, wins).ToString());
		}

		private void ResetScores()
		{
			for (int i = 0; i < _members.Count; i++)
			{
				SetWins(i, 0);
			}
		}

		private void BeginSpectating()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_spectator != (Object)null))
			{
				GameObject val = new GameObject("HowToRounds_Spectator");
				Object.DontDestroyOnLoad((Object)(object)val);
				_spectator = val.AddComponent<SpectatorController>();
				_spectator.Begin(ArenaOrigin);
			}
		}

		private void StopSpectating()
		{
			if (!((Object)(object)_spectator == (Object)null))
			{
				Object.Destroy((Object)(object)((Component)_spectator).gameObject);
				_spectator = null;
			}
		}

		private void BeginNextRound()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			int num = ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_round_winner"), -1);
			bool[] array = AllEligible();
			if (num >= 0 && num < array.Length)
			{
				array[num] = false;
			}
			StartRound(CurrentRoundNumber() + 1, array);
		}

		private int CurrentRoundNumber()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return ParseInt(SteamMatchmaking.GetLobbyData(_lobby, "htr_round_number"), 1);
		}

		private void RefillVitals(bool includeHealth)
		{
			Player[] array = Object.FindObjectsOfType<Player>();
			foreach (Player val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.Vitals == (Object)null))
				{
					if (includeHealth)
					{
						RoundUpgradeEffects.SetHealthToMaximum(val);
					}
					else
					{
						RoundUpgradeEffects.ClampHealthToMaximum(val);
					}
					val.Vitals.RestoreFullness(100);
				}
			}
		}

		private static string EncodeEligible(bool[] eligible)
		{
			char[] array = new char[eligible.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = (eligible[i] ? '1' : '0');
			}
			return new string(array);
		}

		private bool[] DecodeEligible(string value)
		{
			bool[] array = new bool[_members.Count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = i < value.Length && value[i] == '1';
			}
			return array;
		}

		private static int ParseInt(string value, int fallback)
		{
			if (!int.TryParse(value, out var result))
			{
				return fallback;
			}
			return result;
		}

		private static Vector3 GetPhysicalPosition(Player player)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)player.Rigidbody != (Object)null))
			{
				return ((Component)player).transform.position;
			}
			return player.Rigidbody.position;
		}
	}
	internal sealed class CrosshairHud : MonoBehaviour
	{
		private GameObject _canvasObject;

		private CanvasGroup _canvasGroup;

		private void Awake()
		{
			Build();
		}

		private void Update()
		{
			if (!((Object)(object)_canvasGroup == (Object)null))
			{
				bool flag = RoundUpgradeEffects.ModeActive && !RoundUpgradeEffects.SelectionActive && !RoundUpgradeEffects.LocalEliminated && !MainMenuManager.IsInMenu;
				_canvasGroup.alpha = (flag ? 1f : 0f);
			}
		}

		private void Build()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			_canvasObject = new GameObject("HowToRounds_Crosshair");
			_canvasObject.transform.SetParent(((Component)this).transform, false);
			Canvas obj = _canvasObject.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 32060;
			CanvasScaler obj2 = _canvasObject.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			_canvasGroup = _canvasObject.AddComponent<CanvasGroup>();
			_canvasGroup.interactable = false;
			_canvasGroup.blocksRaycasts = false;
			_canvasGroup.alpha = 0f;
			CreateBar("OutlineHorizontal", new Vector2(22f, 4f), Color.black);
			CreateBar("OutlineVertical", new Vector2(4f, 22f), Color.black);
			CreateBar("Horizontal", new Vector2(18f, 2f), Color.white);
			CreateBar("Vertical", new Vector2(2f, 18f), Color.white);
		}

		private void CreateBar(string name, Vector2 size, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(_canvasObject.transform, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0.5f, 0.5f);
			obj.anchorMax = new Vector2(0.5f, 0.5f);
			obj.pivot = new Vector2(0.5f, 0.5f);
			obj.anchoredPosition = Vector2.zero;
			obj.sizeDelta = size;
			Image obj2 = val.AddComponent<Image>();
			((Graphic)obj2).color = color;
			((Graphic)obj2).raycastTarget = false;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_canvasObject != (Object)null)
			{
				Object.Destroy((Object)(object)_canvasObject);
			}
		}
	}
	internal sealed class PlayerHealthHud : MonoBehaviour
	{
		private sealed class Bar
		{
			internal GameObject Root;

			internal RectTransform Rect;

			internal Image Fill;

			internal TextMeshProUGUI Value;

			internal float Displayed = 1f;
		}

		private readonly Dictionary<Player, Bar> _worldBars = new Dictionary<Player, Bar>();

		private readonly List<Player> _remove = new List<Player>();

		private GameObject _canvasObject;

		private RectTransform _canvasRect;

		private Bar _localBar;

		private TMP_FontAsset _font;

		private VitalsUI _nativeVitals;

		private bool _nativeVitalsWasActive;

		private float _nextPlayerRefresh;

		private void Update()
		{
			if (!RoundUpgradeEffects.ModeActive)
			{
				SetCanvasVisible(visible: false);
				RestoreNativeVitals();
				return;
			}
			HideNativeVitals();
			EnsureCanvas();
			SetCanvasVisible(visible: true);
			UpdateLocalBar();
			if (Time.unscaledTime >= _nextPlayerRefresh)
			{
				_nextPlayerRefresh = Time.unscaledTime + 0.25f;
				RefreshPlayers();
			}
			UpdateWorldBars();
		}

		private void OnDestroy()
		{
			RestoreNativeVitals();
		}

		private void HideNativeVitals()
		{
			if ((Object)(object)_nativeVitals == (Object)null)
			{
				_nativeVitals = Object.FindObjectOfType<VitalsUI>();
				if ((Object)(object)_nativeVitals != (Object)null)
				{
					_nativeVitalsWasActive = ((Component)_nativeVitals).gameObject.activeSelf;
				}
			}
			if ((Object)(object)_nativeVitals != (Object)null && ((Component)_nativeVitals).gameObject.activeSelf)
			{
				((Component)_nativeVitals).gameObject.SetActive(false);
			}
		}

		private void RestoreNativeVitals()
		{
			if (!((Object)(object)_nativeVitals == (Object)null))
			{
				if (_nativeVitalsWasActive && !((Component)_nativeVitals).gameObject.activeSelf)
				{
					((Component)_nativeVitals).gameObject.SetActive(true);
				}
				_nativeVitals = null;
			}
		}

		private void EnsureCanvas()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_00b0: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvasObject != (Object)null))
			{
				TMP_Text val = Object.FindObjectOfType<TMP_Text>();
				_font = (((Object)(object)val != (Object)null) ? val.font : null);
				_canvasObject = new GameObject("HowToRounds_HealthHud", new Type[1] { typeof(RectTransform) });
				_canvasObject.transform.SetParent(((Component)this).transform, false);
				_canvasRect = _canvasObject.GetComponent<RectTransform>();
				Canvas obj = _canvasObject.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 32055;
				CanvasScaler obj2 = _canvasObject.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				_localBar = CreateBar((Transform)(object)_canvasRect, "LocalHealth", new Vector2(310f, 78f), local: true);
				RectTransform rect = _localBar.Rect;
				RectTransform rect2 = _localBar.Rect;
				Vector2 val2 = (_localBar.Rect.pivot = Vector2.zero);
				Vector2 anchorMin = (rect2.anchorMax = val2);
				rect.anchorMin = anchorMin;
				_localBar.Rect.anchoredPosition = new Vector2(32f, 42f);
			}
		}

		private void UpdateLocalBar()
		{
			Player localPlayer = Player.LocalPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.Vitals != (Object)null && !RoundUpgradeEffects.LocalEliminated;
			if (_localBar.Root.activeSelf != flag)
			{
				_localBar.Root.SetActive(flag);
			}
			if (flag)
			{
				UpdateBar(_localBar, localPlayer.Vitals.Health, RoundUpgradeEffects.GetMaximumHealth(localPlayer));
			}
		}

		private void RefreshPlayers()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Player> hashSet = new HashSet<Player>();
			Player[] array = Object.FindObjectsOfType<Player>();
			foreach (Player val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)Player.LocalPlayer) && !((Object)(object)val.Vitals == (Object)null))
				{
					hashSet.Add(val);
					if (!_worldBars.ContainsKey(val))
					{
						_worldBars[val] = CreateBar((Transform)(object)_canvasRect, "PlayerHealth", new Vector2(154f, 34f), local: false);
					}
				}
			}
			_remove.Clear();
			foreach (KeyValuePair<Player, Bar> worldBar in _worldBars)
			{
				if ((Object)(object)worldBar.Key == (Object)null || !hashSet.Contains(worldBar.Key))
				{
					_remove.Add(worldBar.Key);
				}
			}
			foreach (Player item in _remove)
			{
				if (_worldBars.TryGetValue(item, out var value) && (Object)(object)value.Root != (Object)null)
				{
					Object.Destroy((Object)(object)value.Root);
				}
				_worldBars.Remove(item);
			}
		}

		private void UpdateWorldBars()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			foreach (KeyValuePair<Player, Bar> worldBar in _worldBars)
			{
				Player key = worldBar.Key;
				Bar value = worldBar.Value;
				if ((Object)(object)key == (Object)null || (Object)(object)key.Vitals == (Object)null || (Object)(object)main == (Object)null)
				{
					value.Root.SetActive(false);
					continue;
				}
				Vector3 val = (((Object)(object)key.Rigidbody != (Object)null) ? key.Rigidbody.position : ((Component)key).transform.position);
				float num = Mathf.Pow(0.8f, (float)RoundUpgradeEffects.GetLevel(key, RoundUpgrade.Miniature));
				Vector3 val2 = main.WorldToScreenPoint(val + Vector3.up * (2.25f * num));
				bool flag = val2.z > 0f && val2.x >= 0f && val2.x <= (float)Screen.width && val2.y >= 0f && val2.y <= (float)Screen.height;
				if (value.Root.activeSelf != flag)
				{
					value.Root.SetActive(flag);
				}
				if (flag)
				{
					((Transform)value.Rect).position = new Vector3(val2.x, val2.y, 0f);
					UpdateBar(value, key.Vitals.Health, RoundUpgradeEffects.GetMaximumHealth(key));
				}
			}
		}

		private static void UpdateBar(Bar bar, int health, int maximum)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			maximum = Mathf.Max(1, maximum);
			int num = Mathf.Clamp(health, 0, maximum);
			float num2 = (float)num / (float)maximum;
			bar.Displayed = Mathf.MoveTowards(bar.Displayed, num2, Time.unscaledDeltaTime * 2.5f);
			bar.Fill.fillAmount = bar.Displayed;
			((Graphic)bar.Fill).color = Color.Lerp(new Color(0.95f, 0.18f, 0.14f), new Color(0.18f, 0.86f, 0.42f), num2);
			((TMP_Text)bar.Value).text = num + " / " + maximum;
		}

		private Bar CreateBar(Transform parent, string name, Vector2 size, bool local)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0065: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_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_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: 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_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Expected O, but got Unknown
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			Bar bar = new Bar();
			bar.Root = new GameObject(name, new Type[1] { typeof(RectTransform) });
			bar.Root.transform.SetParent(parent, false);
			bar.Rect = bar.Root.GetComponent<RectTransform>();
			RectTransform rect = bar.Rect;
			RectTransform rect2 = bar.Rect;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rect2.anchorMax = val;
			rect.anchorMin = val;
			bar.Rect.sizeDelta = size;
			((Graphic)bar.Root.AddComponent<Image>()).color = new Color(0.08f, 0.13f, 0.22f, local ? 0.94f : 0.88f);
			Outline obj = bar.Root.AddComponent<Outline>();
			((Shadow)obj).effectColor = new Color(0.92f, 0.95f, 1f, 0.95f);
			((Shadow)obj).effectDistance = (local ? new Vector2(2f, -2f) : new Vector2(1f, -1f));
			GameObject val2 = new GameObject("Track", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent((Transform)(object)bar.Rect, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			component.anchorMax = val;
			component.anchorMin = val;
			component.anchoredPosition = (Vector2)(local ? new Vector2(0f, -12f) : Vector2.zero);
			component.sizeDelta = (local ? new Vector2(270f, 25f) : new Vector2(140f, 20f));
			((Graphic)val2.AddComponent<Image>()).color = new Color(0.025f, 0.04f, 0.07f, 0.98f);
			GameObject val3 = new GameObject("Fill", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent((Transform)(object)component, false);
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			val = (component2.offsetMin = (component2.offsetMax = Vector2.zero));
			bar.Fill = val3.AddComponent<Image>();
			((Graphic)bar.Fill).color = new Color(0.18f, 0.86f, 0.42f);
			bar.Fill.type = (Type)3;
			bar.Fill.fillMethod = (FillMethod)0;
			bar.Fill.fillOrigin = 0;
			bar.Fill.fillAmount = 1f;
			GameObject val5 = new GameObject("Value", new Type[1] { typeof(RectTransform) });
			val5.transform.SetParent((Transform)(object)bar.Rect, false);
			RectTransform component3 = val5.GetComponent<RectTransform>();
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			component3.anchorMax = val;
			component3.anchorMin = val;
			component3.anchoredPosition = (Vector2)(local ? new Vector2(0f, -12f) : Vector2.zero);
			component3.sizeDelta = (local ? new Vector2(280f, 32f) : new Vector2(150f, 26f));
			bar.Value = val5.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)bar.Value).font = _font;
			}
			((TMP_Text)bar.Value).text = "100 / 100";
			((TMP_Text)bar.Value).fontSize = (local ? 21f : 15f);
			((TMP_Text)bar.Value).fontStyle = (FontStyles)1;
			((TMP_Text)bar.Value).alignment = (TextAlignmentOptions)514;
			((Graphic)bar.Value).color = Color.white;
			((Graphic)bar.Value).raycastTarget = false;
			if (local)
			{
				GameObject val6 = new GameObject("Title", new Type[1] { typeof(RectTransform) });
				val6.transform.SetParent((Transform)(object)bar.Rect, false);
				RectTransform component4 = val6.GetComponent<RectTransform>();
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				component4.anchorMax = val;
				component4.anchorMin = val;
				component4.anchoredPosition = new Vector2(0f, 23f);
				component4.sizeDelta = new Vector2(280f, 26f);
				TextMeshProUGUI val7 = val6.AddComponent<TextMeshProUGUI>();
				if ((Object)(object)_font != (Object)null)
				{
					((TMP_Text)val7).font = _font;
				}
				((TMP_Text)val7).text = "HEALTH";
				((TMP_Text)val7).fontSize = 18f;
				((TMP_Text)val7).alignment = (TextAlignmentOptions)514;
				((Graphic)val7).color = new Color(0.72f, 0.81f, 0.92f);
				((Graphic)val7).raycastTarget = false;
			}
			return bar;
		}

		private void SetCanvasVisible(bool visible)
		{
			if ((Object)(object)_canvasObject != (Object)null && _canvasObject.activeSelf != visible)
			{
				_canvasObject.SetActive(visible);
			}
		}
	}
	[BepInPlugin("com.reysher.howtofish.howtorounds", "How to ROUNDS", "0.17.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal enum LobbyFlow
		{
			None,
			Creating,
			Joining,
			Staging,
			Starting
		}

		internal const string PluginGuid = "com.reysher.howtofish.howtorounds";

		internal const string PluginName = "How to ROUNDS";

		internal const string PluginVersion = "0.17.6";

		internal const string ArenaKey = "htr_arena";

		internal static ManualLogSource Log;

		private RoundsMenuUi _menuUi;

		private Harmony _harmony;

		private CallResult<LobbyMatchList_t> _lobbySearchResult;

		private CSteamID _stagingLobby;

		private string _requestedRoomCode;

		private float _nextMenuProbe;

		private float _nextLobbyRefresh;

		private ArenaRuntime _arenaRuntime;

		private int _joinSearchAttempt;

		internal static Plugin Instance { get; private set; }

		internal LobbyFlow Flow { get; private set; }

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("com.reysher.howtofish.howtorounds");
			try
			{
				_harmony.PatchAll();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("One or more gameplay patches could not be applied: " + ex));
			}
			((Component)this).gameObject.AddComponent<AmmoHud>();
			((Component)this).gameObject.AddComponent<PlayerHealthHud>();
			((Component)this).gameObject.AddComponent<CrosshairHud>();
			_lobbySearchResult = CallResult<LobbyMatchList_t>.Create((APIDispatchDelegate<LobbyMatchList_t>)OnLobbySearchCompleted);
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"How to ROUNDS staging lobby loaded.");
		}

		private void OnDestroy()
		{
			RoundUpgradeEffects.ModeActive = false;
			RoundUpgradeEffects.SelectionActive = false;
			RoundUpgradeEffects.LocalEliminated = false;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			if (Time.unscaledTime >= _nextMenuProbe)
			{
				_nextMenuProbe = Time.unscaledTime + 0.3f;
				EnsureMenuUi();
				if ((Object)(object)_menuUi != (Object)null)
				{
					_menuUi.SetMenuVisible(IsAtMainMenu());
				}
			}
			if (Flow == LobbyFlow.Starting && _arenaRuntime != null)
			{
				_arenaRuntime.Tick();
			}
			if (Flow == LobbyFlow.Staging && Time.unscaledTime >= _nextLobbyRefresh)
			{
				_nextLobbyRefresh = Time.unscaledTime + 0.35f;
				RefreshLobby();
			}
		}

		private void EnsureMenuUi()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (!((Object)(object)_menuUi != (Object)null) && IsAtMainMenu())
			{
				GameObject val = new GameObject("HowToRounds_MenuUi");
				Object.DontDestroyOnLoad((Object)(object)val);
				_menuUi = val.AddComponent<RoundsMenuUi>();
				_menuUi.Initialize(this);
			}
		}

		private static bool IsAtMainMenu()
		{
			if (MainMenuManager.IsInMenu)
			{
				return (Object)(object)Object.FindObjectOfType<MainMenuManager>() != (Object)null;
			}
			return false;
		}

		internal bool ShouldInterceptLobbyCreated()
		{
			return Flow == LobbyFlow.Creating;
		}

		internal bool IsDuplicateStagingEntry(ulong lobbyId)
		{
			if (Flow == LobbyFlow.Staging)
			{
				return _stagingLobby.m_SteamID == lobbyId;
			}
			return false;
		}

		internal void CreateRoom()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (Flow != LobbyFlow.None)
			{
				return;
			}
			try
			{
				_menuUi.SetBrowserStatus("Creating Steam room...");
				ServerSaveObject curServerSave = SaveManager.CurServerSave;
				if (curServerSave == null)
				{
					SaveManager.CreateServer("How To ROUNDS", true, true, (Difficulty)1);
					curServerSave = SaveManager.CurServerSave;
				}
				if (curServerSave == null)
				{
					throw new InvalidOperationException("Could not prepare the How to ROUNDS world.");
				}
				curServerSave.UseSteam = true;
				curServerSave.IsPublic = true;
				Flow = LobbyFlow.Creating;
				SteamMatchmaking.CreateLobby((ELobbyType)2, GetMaxPlayers());
			}
			catch (Exception ex)
			{
				Flow = LobbyFlow.None;
				Log.LogError((object)ex);
				_menuUi.SetBrowserStatus("Could not create the room. Check the console.", error: true);
			}
		}

		internal void JoinRoom(string code)
		{
			if (Flow != LobbyFlow.None)
			{
				return;
			}
			if (!RoomCode.TryNormalize(code, out var code2))
			{
				_menuUi.SetBrowserStatus("Enter a valid 5-character room code.", error: true);
				return;
			}
			try
			{
				Flow = LobbyFlow.Joining;
				_requestedRoomCode = code2;
				_joinSearchAttempt = 0;
				_menuUi.SetBrowserStatus("Searching for room " + code2 + "...");
				RequestRoomSearch();
			}
			catch (Exception ex)
			{
				Flow = LobbyFlow.None;
				Log.LogError((object)ex);
				_menuUi.SetBrowserStatus("Could not join the room. Check the code.", error: true);
			}
		}

		private void OnLobbySearchCompleted(LobbyMatchList_t callback, bool ioFailure)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			if (Flow != LobbyFlow.Joining)
			{
				return;
			}
			if (ioFailure || callback.m_nLobbiesMatching == 0)
			{
				if (!ioFailure && ++_joinSearchAttempt < 4)
				{
					_menuUi.SetBrowserStatus("Steam is locating room " + _requestedRoomCode + "... attempt " + (_joinSearchAttempt + 1) + "/4");
					((MonoBehaviour)this).StartCoroutine(RetryRoomSearch());
				}
				else
				{
					Flow = LobbyFlow.None;
					_menuUi.SetBrowserStatus(ioFailure ? "Steam could not search for rooms. Try again." : ("Room " + _requestedRoomCode + " is not visible. Make sure the host uses mod 0.17.6."), error: true);
				}
				return;
			}
			CSteamID lobbyByIndex = SteamMatchmaking.GetLobbyByIndex(0);
			if (lobbyByIndex.m_SteamID == 0L)
			{
				Flow = LobbyFlow.None;
				_menuUi.SetBrowserStatus("Steam returned an invalid room.", error: true);
				return;
			}
			string lobbyData = SteamMatchmaking.GetLobbyData(lobbyByIndex, "how_to_rounds");
			if (lobbyData != "0.17.6")
			{
				Flow = LobbyFlow.None;
				_menuUi.SetBrowserStatus("Room found, but versions differ (host " + (string.IsNullOrEmpty(lobbyData) ? "unknown" : lobbyData) + ", you 0.17.6).", error: true);
			}
			else
			{
				_menuUi.SetBrowserStatus("Joining room " + _requestedRoomCode + "...");
				SteamManager.JoinLobby(lobbyByIndex.m_SteamID);
			}
		}

		private void RequestRoomSearch()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			SteamMatchmaking.AddRequestLobbyListStringFilter("htr_code", _requestedRoomCode, (ELobbyComparison)0);
			SteamMatchmaking.AddRequestLobbyListDistanceFilter((ELobbyDistanceFilter)3);
			_lobbySearchResult.Set(SteamMatchmaking.RequestLobbyList(), (APIDispatchDelegate<LobbyMatchList_t>)null);
		}

		private IEnumerator RetryRoomSearch()
		{
			yield return (object)new WaitForSecondsRealtime(1.2f);
			if (Flow == LobbyFlow.Joining)
			{
				RequestRoomSearch();
			}
		}

		internal void OnLobbyCreated(LobbyCreated_t callback)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			if ((int)callback.m_eResult != 1 || callback.m_ulSteamIDLobby == 0L)
			{
				Flow = LobbyFlow.None;
				_menuUi.SetBrowserStatus("Steam could not create the room.", error: true);
			}
			else
			{
				EnterStagingLobby(new CSteamID(callback.m_ulSteamIDLobby), createdByLocalPlayer: true);
			}
		}

		internal void OnLobbyEntered(LobbyEnter_t callback)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (callback.m_EChatRoomEnterResponse != 1 || callback.m_ulSteamIDLobby == 0L)
			{
				Flow = LobbyFlow.None;
				_menuUi.SetBrowserStatus("Steam rejected the room connection.", error: true);
				return;
			}
			CSteamID val = default(CSteamID);
			((CSteamID)(ref val))..ctor(callback.m_ulSteamIDLobby);
			string lobbyData = SteamMatchmaking.GetLobbyData(val, "version");
			string lobbyData2 = SteamMatchmaking.GetLobbyData(val, "how_to_rounds");
			if (lobbyData != Application.version || lobbyData2 != "0.17.6")
			{
				SteamMatchmaking.LeaveLobby(val);
				Flow = LobbyFlow.None;
				_menuUi.SetBrowserStatus("Room version mismatch. Install the same game and mod version.", error: true);
			}
			else
			{
				EnterStagingLobby(val, createdByLocalPlayer: false);
			}
		}

		private void EnterStagingLobby(CSteamID lobby, bool createdByLocalPlayer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			_stagingLobby = lobby;
			SetCurrentLobbyId(lobby);
			Flow = LobbyFlow.Staging;
			if (createdByLocalPlayer)
			{
				_requestedRoomCode = RoomCode.Generate();
				SteamMatchmaking.SetLobbyData(lobby, "how_to_rounds", "0.17.6");
				SteamMatchmaking.SetLobbyData(lobby, "htr_state", "waiting");
				SteamMatchmaking.SetLobbyData(lobby, "htr_arena", "arena03");
				SteamMatchmaking.SetLobbyData(lobby, "htr_code", _requestedRoomCode);
				SteamMatchmaking.SetLobbyData(lobby, "name", SteamFriends.GetPersonaName() + "'s How to ROUNDS lobby");
				SteamMatchmaking.SetLobbyData(lobby, "version", Application.version);
				SteamMatchmaking.SetLobbyType(lobby, (ELobbyType)2);
				SteamMatchmaking.SetLobbyJoinable(lobby, true);
			}
			string code = (GUIUtility.systemCopyBuffer = (createdByLocalPlayer ? _requestedRoomCode : SteamMatchmaking.GetLobbyData(lobby, "htr_code")));
			_menuUi.ShowLobby(code, IsLocalLobbyOwner());
			RefreshLobby();
		}

		private void RefreshLobby()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0055: 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_005c: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if (_stagingLobby.m_SteamID == 0L)
			{
				return;
			}
			try
			{
				int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(_stagingLobby);
				List<string> list = new List<string>(Math.Max(1, numLobbyMembers));
				CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(_stagingLobby);
				if (lobbyOwner.m_SteamID != 0L)
				{
					list.Add(GetPersonaName(lobbyOwner));
				}
				for (int i = 0; i < numLobbyMembers; i++)
				{
					CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(_stagingLobby, i);
					if (lobbyMemberByIndex != lobbyOwner)
					{
						list.Add(GetPersonaName(lobbyMemberByIndex));
					}
				}
				bool flag = IsLocalLobbyOwner();
				_menuUi.UpdateLobbyMembers(list, flag);
				if (!flag && SteamMatchmaking.GetLobbyData(_stagingLobby, "htr_state") == "starting")
				{
					BeginClientStart();
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Lobby refresh failed: " + ex.Message));
			}
		}

		private bool IsLocalLobbyOwner()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//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 (_stagingLobby.m_SteamID != 0L)
			{
				return SteamMatchmaking.GetLobbyOwner(_stagingLobby) == SteamUser.GetSteamID();
			}
			return false;
		}

		private static string GetPersonaName(CSteamID player)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			string text = ((player == SteamUser.GetSteamID()) ? SteamFriends.GetPersonaName() : SteamFriends.GetFriendPersonaName(player));
			if (!string.IsNullOrWhiteSpace(text) && !(text == "[unknown]"))
			{
				return text;
			}
			return "Steam player";
		}

		internal void StartMatch()
		{
			//IL_0021: 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)
			if (Flow == LobbyFlow.Staging && IsLocalLobbyOwner())
			{
				Flow = LobbyFlow.Starting;
				string text = SelectArenaForMatch();
				SteamMatchmaking.SetLobbyData(_stagingLobby, "htr_arena", text);
				SteamMatchmaking.SetLobbyData(_stagingLobby, "htr_state", "starting");
				_menuUi.SetLobbyStatus("Starting " + ArenaRuntime.DisplayName(text) + "...");
				((MonoBehaviour)this).StartCoroutine(StartHostAfterSignal());
			}
		}

		private string SelectArenaForMatch()
		{
			List<string> list = ArenaRuntime.FindInstalledArenas(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty);
			if (list.Count == 0)
			{
				Log.LogWarning((object)"No howtorounds_arenaNN bundles were found beside the plugin.");
				return "arena03";
			}
			string text = list[Random.Range(0, list.Count)];
			Log.LogInfo((object)("Host selected " + ArenaRuntime.DisplayName(text) + " from " + list.Count + " installed arena(s)."));
			return text;
		}

		private IEnumerator StartHostAfterSignal()
		{
			yield return (object)new WaitForSecondsRealtime(0.55f);
			if (!((Object)(object)ConnectionManager.Instance != (Object)null) || !ConnectionManager.Instance.CreateOnlineLobby(GetMaxPlayers()))
			{
				Flow = LobbyFlow.Staging;
				SteamMatchmaking.SetLobbyData(_stagingLobby, "htr_state", "waiting");
				_menuUi.SetLobbyStatus("Could not start the host.", error: true);
				yield break;
			}
			yield return (object)new WaitForSecondsRealtime(0.25f);
			if (!((Object)(object)ConnectionManager.Instance != (Object)null) || !ConnectionManager.Instance.JoinOnlineLobby(_stagingLobby))
			{
				Flow = LobbyFlow.Staging;
				SteamMatchmaking.SetLobbyData(_stagingLobby, "htr_state", "waiting");
				_menuUi.SetLobbyStatus("Host server started, but the local player could not connect.", error: true);
			}
			else
			{
				BeginArenaDeployment();
			}
		}

		private void BeginClientStart()
		{
			if (Flow == LobbyFlow.Staging)
			{
				Flow = LobbyFlow.Starting;
				_menuUi.SetLobbyStatus("Host is starting the match...");
				((MonoBehaviour)this).StartCoroutine(StartClientAfterHost());
			}
		}

		private IEnumerator StartClientAfterHost()
		{
			yield return (object)new WaitForSecondsRealtime(1.1f);
			if (!((Object)(object)ConnectionManager.Instance != (Object)null) || !ConnectionManager.Instance.JoinOnlineLobby(_stagingLobby))
			{
				Flow = LobbyFlow.Staging;
				_menuUi.SetLobbyStatus("Could not connect to the host.", error: true);
			}
			else
			{
				BeginArenaDeployment();
			}
		}

		private void BeginArenaDeployment()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (_arenaRuntime == null)
			{
				_arenaRuntime = new ArenaRuntime(this);
			}
			_arenaRuntime.Begin(_stagingLobby);
		}

		internal void LeaveStagingLobby()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			if (_stagingLobby.m_SteamID != 0L)
			{
				SteamMatchmaking.LeaveLobby(_stagingLobby);
			}
			_stagingLobby = default(CSteamID);
			_requestedRoomCode = null;
			SetCurrentLobbyId(default(CSteamID));
			Flow = LobbyFlow.None;
			_menuUi.HideLobby();
		}

		private static void SetCurrentLobbyId(CSteamID lobby)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			AccessTools.Field(typeof(SteamManager), "<CurrentLobbyID>k__BackingField")?.SetValue(null, lobby);
		}

		private static int GetMaxPlayers()
		{
			if (!(AccessTools.Field(typeof(SteamManager), "MaxPlayers")?.GetValue(null) is int num) || num <= 0)
			{
				return 4;
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(SteamManager), "OnLobbyCreated")]
	internal static class StagingLobbyCreatedPatch
	{
		private static bool Prefix(LobbyCreated_t callback)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null || !instance.ShouldInterceptLobbyCreated())
			{
				return true;
			}
			instance.OnLobbyCreated(callback);
			return false;
		}
	}
	[HarmonyPatch(typeof(SteamManager), "OnLobbyEntered")]
	internal static class StagingLobbyEnteredPatch
	{
		private static bool Prefix(LobbyEnter_t callback)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			if (instance.Flow == Plugin.LobbyFlow.Joining)
			{
				instance.OnLobbyEntered(callback);
				return false;
			}
			return !instance.IsDuplicateStagingEntry(callback.m_ulSteamIDLobby);
		}
	}
	internal static class RoomCode
	{
		private const string Alphabet = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";

		internal static string Generate()
		{
			byte[] array = Guid.NewGuid().ToByteArray();
			StringBuilder stringBuilder = new StringBuilder(5);
			for (int i = 0; i < 5; i++)
			{
				stringBuilder.Append("ABCDEFGHJKLMNPQRSTUVWXYZ23456789"[array[i] % "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".Length]);
			}
			return stringBuilder.ToString();
		}

		internal static bool TryNormalize(string input, out string code)
		{
			code = (string.IsNullOrWhiteSpace(input) ? string.Empty : input.Trim().Replace("-", string.Empty).Replace(" ", string.Empty)
				.ToUpperInvariant());
			if (code.Length != 5)
			{
				return false;
			}
			string text = code;
			foreach (char value in text)
			{
				if ("ABCDEFGHJKLMNPQRSTUVWXYZ23456789".IndexOf(value) < 0)
				{
					return false;
				}
			}
			return true;
		}
	}
	internal sealed class RoundsMenuUi : MonoBehaviour
	{
		private static readonly Color VanillaPanel = new Color(0.1f, 0.2f, 0.34f, 0.94f);

		private static readonly Color VanillaRow = new Color(0.13f, 0.25f, 0.4f, 0.92f);

		private static readonly Color White = new Color(0.97f, 0.98f, 1f, 1f);

		private static readonly Color Muted = new Color(0.76f, 0.82f, 0.88f, 1f);

		private static readonly Color Error = new Color(1f, 0.48f, 0.38f, 1f);

		private Plugin _plugin;

		private Canvas _canvas;

		private GameObject _menuButton;

		private GameObject _modal;

		private GameObject _browserPanel;

		private GameObject _lobbyPanel;

		private TMP_InputField _codeInput;

		private TMP_Text _browserStatus;

		private TMP_Text _lobbyCode;

		private TMP_Text _lobbyStatus;

		private TMP_Text _hostHint;

		private readonly List<TMP_Text> _memberRows = new List<TMP_Text>();

		private GameObject _startButton;

		private TMP_FontAsset _font;

		private Sprite _buttonSprite;

		private Color _buttonColor = new Color(0.12f, 0.25f, 0.42f, 0.92f);

		private bool _modalOpen;

		internal void Initialize(Plugin plugin)
		{
			_plugin = plugin;
			TryAttachVanillaButton();
			BuildModal();
			if ((Object)(object)_menuButton == (Object)null)
			{
				CreateFallbackMenuButton();
			}
		}

		internal void SetMenuVisible(bool visible)
		{
			if (visible)
			{
				TryAttachVanillaButton();
			}
			if ((Object)(object)_menuButton != (Object)null)
			{
				_menuButton.SetActive(visible && !_modalOpen);
			}
			if (!visible && (Object)(object)_modal != (Object)null)
			{
				_modal.SetActive(false);
			}
			else if (visible && _modalOpen && (Object)(object)_modal != (Object)null)
			{
				_modal.SetActive(true);
			}
		}

		internal void SetBrowserStatus(string message, bool error = false)
		{
			//IL_002b: 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)
			if (!((Object)(object)_browserStatus == (Object)null))
			{
				_browserStatus.text = message;
				((Graphic)_browserStatus).color = (error ? Error : Muted);
			}
		}

		internal void ShowLobby(string code, bool isHost)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			_modalOpen = true;
			_modal.SetActive(true);
			_browserPanel.SetActive(false);
			_lobbyPanel.SetActive(true);
			if ((Object)(object)_menuButton != (Object)null)
			{
				_menuButton.SetActive(false);
			}
			_lobbyCode.text = "ROOM CODE:  " + code;
			_lobbyStatus.text = "Waiting for players...";
			((Graphic)_lobbyStatus).color = Muted;
			SetHostControls(isHost);
		}

		internal void UpdateLobbyMembers(IReadOnlyList<string> members, bool isHost)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _memberRows.Count; i++)
			{
				if (i < members.Count)
				{
					_memberRows[i].text = i + 1 + ".  " + members[i] + ((i == 0) ? "   HOST" : string.Empty);
				}
				else
				{
					_memberRows[i].text = i + 1 + ".  Waiting for player...";
				}
				((Graphic)_memberRows[i]).color = (Color)((i < members.Count) ? White : new Color(Muted.r, Muted.g, Muted.b, 0.55f));
			}
			SetHostControls(isHost);
		}

		internal void SetLobbyStatus(string message, bool error = false)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			_lobbyStatus.text = message;
			((Graphic)_lobbyStatus).color = (error ? Error : Muted);
		}

		internal void HideLobby()
		{
			_modalOpen = false;
			_modal.SetActive(false);
			_browserPanel.SetActive(true);
			_lobbyPanel.SetActive(false);
			if ((Object)(object)_menuButton != (Object)null)
			{
				_menuButton.SetActive(true);
			}
		}

		private void TryAttachVanillaButton()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_005a: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if ((Object)(object)_menuButton != (Object)null)
			{
				return;
			}
			Button val = FindCreateGameButton();
			if (!((Object)(object)val == (Object)null))
			{
				TMP_Text componentInChildren = ((Component)val).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					_font = componentInChildren.font;
				}
				Image component = ((Component)val).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					_buttonSprite = component.sprite;
					_buttonColor = ((Graphic)component).color;
				}
				_menuButton = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent, false);
				((Object)_menuButton).name = "HowToRounds_VanillaMenuButton";
				Button component2 = _menuButton.GetComponent<Button>();
				component2.onClick = new ButtonClickedEvent();
				((UnityEvent)component2.onClick).AddListener(new UnityAction(OpenBrowser));
				TMP_Text[] componentsInChildren = _menuButton.GetComponentsInChildren<TMP_Text>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].text = "HOW TO ROUNDS";
				}
				_menuButton.AddComponent<VanillaButtonLabelLock>().Initialize("HOW TO ROUNDS");
				RectTransform component3 = ((Component)val).GetComponent<RectTransform>();
				RectTransform component4 = _menuButton.GetComponent<RectTransform>();
				if ((Object)(object)((Component)((Component)val).transform.parent).GetComponent<LayoutGroup>() != (Object)null)
				{
					_menuButton.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex());
					return;
				}
				Vector2 anchoredPosition = component3.anchoredPosition;
				Rect rect = component3.rect;
				component4.anchoredPosition = anchoredPosition + new Vector2(0f, ((Rect)(ref rect)).height + 10f);
			}
		}

		private static Button FindCreateGameButton()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Button result = null;
			ButtonManager val = Object.FindObjectOfType<ButtonManager>();
			Button[] array = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentsInChildren<Button>(true) : Resources.FindObjectsOfTypeAll<Button>());
			foreach (Button val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Scene scene = ((Component)val2).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					continue;
				}
				for (int j = 0; j < ((UnityEventBase)val2.onClick).GetPersistentEventCount(); j++)
				{
					if (((UnityEventBase)val2.onClick).GetPersistentMethodName(j) == "ToggleCreateServerButton")
					{
						return val2;
					}
				}
				TMP_Text componentInChildren = ((Component)val2).GetComponentInChildren<TMP_Text>(true);
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					string text = componentInChildren.text.ToLowerInvariant();
					if (text.Contains("crear partida") || text.Contains("create game") || text.Contains("create server"))
					{
						result = val2;
					}
				}
			}
			return result;
		}

		private void CreateFallbackMenuButton()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0082: 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_0099: 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)
			if (!((Object)(object)_menuButton != (Object)null) && !((Object)(object)_canvas == (Object)null))
			{
				_menuButton = Button(((Component)_canvas).transform, "HOW TO ROUNDS", new Vector2(300f, 60f), new UnityAction(OpenBrowser));
				((Object)_menuButton).name = "HowToRounds_FallbackMenuButton";
				RectTransform component = _menuButton.GetComponent<RectTransform>();
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(0f, 0f);
				component.anchorMax = val;
				component.anchorMin = val;
				component.pivot = new Vector2(0f, 0.5f);
				component.anchoredPosition = new Vector2(40f, 420f);
				Plugin.Log.LogWarning((object)"The vanilla Create Game button was not found; using the standalone How To Rounds menu button.");
			}
		}

		private void BuildModal()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_font == (Object)null)
			{
				TMP_Text val = Object.FindObjectOfType<TMP_Text>();
				if ((Object)(object)val != (Object)null)
				{
					_font = val.font;
				}
			}
			GameObject val2 = UiObject("Canvas", ((Component)this).transform);
			_canvas = val2.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 32000;
			CanvasScaler obj = val2.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.matchWidthOrHeight = 0.5f;
			val2.AddComponent<GraphicRaycaster>();
			_modal = Panel(val2.transform, "RoundsModal", new Vector2(700f, 570f), VanillaPanel, outline: true);
			RectTransform component = _modal.GetComponent<RectTransform>();
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			component.anchorMax = val3;
			component.anchorMin = val3;
			component.anchoredPosition = new Vector2(115f, 0f);
			Text(_modal.transform, "HOW TO ROUNDS", 42f, (FontStyles)0, White, new Vector2(0f, 238f), new Vector2(620f, 58f), (TextAlignmentOptions)514);
			Text(_modal.transform, "COMPETITIVE FISHING COMBAT", 18f, (FontStyles)0, Muted, new Vector2(0f, 196f), new Vector2(620f, 30f), (TextAlignmentOptions)514);
			_browserPanel = UiObject("B