Decompiled source of SinnerPeak v1.0.6

plugins/StealthJug.SinnerPeak.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using SinnerPeak;
using SinnerPeak.Core;
using SinnerPeak.Groups;
using SinnerPeak.Helpers;
using SinnerPeak.Networking;
using SinnerPeak.Patches;
using SinnerPeak.Revive;
using SinnerPeak.UI;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Zorro.Core;

[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("StealthJug.SinnerPeak")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyInformationalVersion("1.0.6+8970c60684fc8e26f1a0695822d1b7ab74135654")]
[assembly: AssemblyProduct("StealthJug.SinnerPeak")]
[assembly: AssemblyTitle("SinnerPeak")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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;
		}
	}
}
[HarmonyPatch]
public static class Patch_LobbyLoadingFinished
{
	private static bool joinLinkSent;

	private static MethodBase TargetMethod()
	{
		Type typeFromHandle = typeof(LoadingScreen);
		Type[] nestedTypes = typeFromHandle.GetNestedTypes(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		Type type = null;
		Type[] array = nestedTypes;
		foreach (Type type2 in array)
		{
			if (type2.Name.Contains("LoadingRoutine"))
			{
				type = type2;
				break;
			}
		}
		if (type == null)
		{
			Plugin.Log.LogError((object)"[SinnerPeak] ERROR: Could not find LoadingRoutine state machine!");
			return null;
		}
		return type.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
	}

	[HarmonyPostfix]
	private static void AfterLoadingFinished(object __instance)
	{
		FieldInfo field = __instance.GetType().GetField("<>1__state", BindingFlags.Instance | BindingFlags.NonPublic);
		if (field == null)
		{
			return;
		}
		int num = (int)field.GetValue(__instance);
		if (num == -1 && PhotonNetwork.IsMasterClient && !joinLinkSent)
		{
			joinLinkSent = true;
			string joinURI = SteamJoinLink.GetJoinURI();
			Plugin.Log.LogInfo((object)("[SinnerPeak] Steam Join Link: " + joinURI));
			if (!string.IsNullOrWhiteSpace(joinURI))
			{
				string message = "**Join the game:**\t" + joinURI + "\n";
				Webhook.Send(message);
			}
		}
	}
}
public class SinnerPeakRuntime : MonoBehaviour
{
	private int f;

	private void Update()
	{
		if (++f == 10)
		{
			f = 0;
			Patch_Biome.UpdateCampfireCheck();
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace SinnerPeak
{
	[BepInPlugin("stealthjug.sinnerpeak", "SinnerPeak", "1.0.6")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony _harmony;

		public static ConfigEntry<bool> ShowLeaderboard;

		public static ConfigEntry<bool> UseGroupLeaderboard;

		public static ConfigEntry<bool> UseTMPLeaderboard;

		public static ConfigEntry<KeyboardShortcut> ToggleLeaderboardKey;

		public static ConfigEntry<KeyboardShortcut> TogglePointsKey;

		public static ConfigEntry<KeyboardShortcut> ToggleGroupManagerKey;

		public static ConfigEntry<int> PointsFirst;

		public static ConfigEntry<int> PointsSecond;

		public static ConfigEntry<int> PointsThird;

		public static ConfigEntry<string> FinishWebhook;

		public static bool ShowPointsMode = false;

		public static Dictionary<int, int> TotalPoints = new Dictionary<int, int>();

		public static string CurrentBiomeName = "UNKNOWN";

		public static ConfigEntry<float> ReviveRadius;

		public static ConfigEntry<int> MaxTokens;

		public static ConfigEntry<int> StartTokens;

		public static ConfigEntry<KeyboardShortcut> ReviveKey;

		public void Awake()
		{
			//IL_0094: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Expected O, but got Unknown
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Expected O, but got Unknown
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Expected O, but got Unknown
			//IL_02bc: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"SinnerPeak loading…");
			ShowLeaderboard = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Show Leaderboard", true, "Whether the leaderboard is visible.");
			UseGroupLeaderboard = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Use Group Leaderboard", false, "Enable group-based leaderboard mode.");
			UseTMPLeaderboard = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Use Stylized Leaderboard", true, "Use the TextMeshPro leaderboard instead of IMGUI.");
			ToggleLeaderboardKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "ToggleLeaderboard", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Toggle leaderboard window.");
			TogglePointsKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "TogglePoints", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Toggle between normal and points leaderboard");
			ToggleGroupManagerKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "ToggleGroupManager", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Toggle group manager UI (host only)");
			PointsFirst = ((BaseUnityPlugin)this).Config.Bind<int>("Points", "FirstPlace", 5, "Points for finishing 1st");
			PointsSecond = ((BaseUnityPlugin)this).Config.Bind<int>("Points", "SecondPlace", 3, "Points for finishing 2nd");
			PointsThird = ((BaseUnityPlugin)this).Config.Bind<int>("Points", "ThirdPlace", 1, "Points for finishing 3rd");
			FinishWebhook = ((BaseUnityPlugin)this).Config.Bind<string>("Webhook", "FinishWebhook", "", "Webhook URL for biome finish notifications. Leave empty to disable.");
			ReviveRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "ReviveRadius", 50f, "Maximum distance (in meters) to revive a teammate. (HOST ONLY)");
			MaxTokens = ((BaseUnityPlugin)this).Config.Bind<int>("Revive", "MaxTokens", 3, "Maximum revive tokens a group can hold. (HOST ONLY)");
			StartTokens = ((BaseUnityPlugin)this).Config.Bind<int>("Revive", "StartTokens", 1, "Number of revive tokens each group starts with. (HOST ONLY)");
			ReviveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Revive", "ReviveKey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Key used for modded revive (F-hold revive).");
			GameObject val = new GameObject("SinnerPeak_UI");
			val.AddComponent<LeaderboardUI>();
			val.AddComponent<GroupManagerUI>();
			Object.DontDestroyOnLoad((Object)(object)val);
			_harmony = new Harmony("stealthjug.sinnerpeak");
			_harmony.PatchAll();
			GameObject val2 = new GameObject("SinnerPeak_Runtime");
			val2.AddComponent<SinnerPeakRuntime>();
			val2.AddComponent<ReviveRuntime>();
			Object.DontDestroyOnLoad((Object)(object)val2);
			GameObject val3 = new GameObject("NetworkGroupSync");
			PhotonView val4 = val3.AddComponent<PhotonView>();
			val4.ViewID = 999999900;
			val3.AddComponent<NetworkGroupSync>();
			Object.DontDestroyOnLoad((Object)(object)val3);
			Player localPlayer = PhotonNetwork.LocalPlayer;
			Hashtable val5 = new Hashtable();
			((Dictionary<object, object>)val5).Add((object)"SP_Modded", (object)true);
			localPlayer.SetCustomProperties(val5, (Hashtable)null, (WebFlags)null);
			((Component)this).gameObject.AddComponent<ReviveBootstrap>();
			Log.LogInfo((object)"SinnerPeak initialized successfully.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Log.LogInfo((object)"SinnerPeak unloaded.");
		}
	}
}
namespace SinnerPeak.UI
{
	public class GroupManagerUI : MonoBehaviourPunCallbacks
	{
		private bool open;

		private GUIStyle richToggle;

		private Rect windowRect = new Rect(200f, 200f, 560f, 720f);

		private Vector2 scrollGroups;

		private Vector2 scrollPlayers;

		private Vector2 giveItemScroll;

		private string newGroupName = "";

		private int newGroupSkinIndex;

		private bool dropdownOpen;

		private int selectedGroupIndex;

		private GUIStyle skinButtonStyle;

		private GUIStyle skinButtonSelectedStyle;

		private GUIStyle richLabel;

		private GUIStyle headerLabel;

		private int tabIndex;

		private readonly string[] tabs = new string[3] { "Groups", "Host Tools", "Players" };

		private int autoScrollTargetIndex = -1;

		private int selectedHostPlayerIndex;

		private int selectedHostGroupIndex;

		private List<Character> cachedCharacters = new List<Character>();

		private string[] cachedPlayerNames = Array.Empty<string>();

		private float nextPlayerCacheTime;

		private bool hostPlayerDropdownOpen;

		private bool groupCacheInitialized;

		private int lastGroupCount = -1;

		private string[] cachedGroupNames = Array.Empty<string>();

		private bool hostGroupDropdownOpen;

		private bool giveItemPopupOpen;

		private int giveItemTargetActor = -1;

		private string giveItemSlotLabel = "";

		private Rect giveItemPopupRect = new Rect(300f, 300f, 300f, 400f);

		private List<(string name, ushort id)> dynamicGiveItemList = new List<(string, ushort)>();

		private bool giveItemListInitialized;

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Plugin.ToggleGroupManagerKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				open = !open;
			}
		}

		private void OnGUI()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if (!open)
			{
				return;
			}
			EnsureStyles();
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				windowRect = GUI.Window(99123, windowRect, new WindowFunction(DrawLoadingWindow), "Group Manager");
				return;
			}
			int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
			string groupOfPlayer = GroupManager.GetGroupOfPlayer(actorNumber);
			bool isMasterClient = PhotonNetwork.IsMasterClient;
			bool flag = GroupManager.IsSpectatorGroup(groupOfPlayer);
			int actorNumber2 = PhotonNetwork.MasterClient.ActorNumber;
			if (ModdedClientRegistry.IsModded(actorNumber2) && (isMasterClient || flag))
			{
				windowRect = GUI.Window(99123, windowRect, new WindowFunction(DrawWindow), "Group Manager");
				if (giveItemPopupOpen)
				{
					giveItemPopupRect = GUI.Window(99124, giveItemPopupRect, new WindowFunction(DrawGiveItemPopup), "Give Item");
				}
			}
		}

		private void DrawLoadingWindow(int id)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			GUILayout.Label("<b>Loading…</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void EnsureStyles()
		{
			//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)
			//IL_0024: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if (richLabel == null)
			{
				richLabel = new GUIStyle(GUI.skin.label)
				{
					richText = true
				};
			}
			if (headerLabel == null)
			{
				headerLabel = new GUIStyle(GUI.skin.label)
				{
					richText = true,
					fontSize = 14
				};
			}
		}

		private void DrawWindow(int id)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			for (int i = 0; i < tabs.Length; i++)
			{
				GUIStyle val = ((i == tabIndex) ? GUI.skin.button : GUI.skin.box);
				if (GUILayout.Button(tabs[i], val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					tabIndex = i;
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			if (tabIndex == 0)
			{
				DrawGroupsTab();
			}
			else if (tabIndex == 1)
			{
				DrawHostToolsTab();
			}
			else
			{
				DrawModdedPlayersTab();
			}
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void EnsurePlayerCache()
		{
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				cachedCharacters.Clear();
				cachedPlayerNames = Array.Empty<string>();
				nextPlayerCacheTime = Time.time + 3f;
			}
			else
			{
				if (Time.time < nextPlayerCacheTime)
				{
					return;
				}
				cachedCharacters = PlayerHandler.GetAllPlayerCharacters() ?? new List<Character>();
				int count = cachedCharacters.Count;
				cachedPlayerNames = new string[count];
				for (int i = 0; i < count; i++)
				{
					Character val = cachedCharacters[i];
					if ((Object)(object)val == (Object)null || (Object)(object)((MonoBehaviourPun)val).photonView == (Object)null || ((MonoBehaviourPun)val).photonView.Owner == null)
					{
						cachedPlayerNames[i] = "Unknown";
						continue;
					}
					Player owner = ((MonoBehaviourPun)val).photonView.Owner;
					cachedPlayerNames[i] = owner.NickName + " (" + owner.ActorNumber + ")";
				}
				nextPlayerCacheTime = Time.time + 3f;
			}
		}

		private void EnsureGroupCache()
		{
			int count = GroupManager.Groups.Count;
			if (groupCacheInitialized && count == lastGroupCount)
			{
				return;
			}
			Dictionary<string, Group>.KeyCollection keys = GroupManager.Groups.Keys;
			cachedGroupNames = new string[keys.Count];
			int num = 0;
			foreach (string item in keys)
			{
				cachedGroupNames[num++] = item;
			}
			lastGroupCount = count;
			groupCacheInitialized = true;
		}

		private static Character GetRealCharacter(int actor)
		{
			Character result = null;
			foreach (Character allPlayerCharacter in PlayerHandler.GetAllPlayerCharacters())
			{
				if (!((Object)(object)allPlayerCharacter == (Object)null) && !((Object)(object)((MonoBehaviourPun)allPlayerCharacter).photonView == (Object)null) && ((MonoBehaviourPun)allPlayerCharacter).photonView.OwnerActorNr == actor && (!((Object)(object)allPlayerCharacter.data != (Object)null) || !allPlayerCharacter.data.dead))
				{
					result = allPlayerCharacter;
					break;
				}
			}
			return result;
		}

		private void DrawGroupsTab()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0045: 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_0059: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			Color color = GUI.color;
			GUI.color = (Plugin.UseGroupLeaderboard.Value ? Color.green : Color.white);
			if (richToggle == null)
			{
				richToggle = new GUIStyle(GUI.skin.toggle)
				{
					richText = true,
					fontSize = 14
				};
			}
			bool flag = GUILayout.Toggle(Plugin.UseGroupLeaderboard.Value, "<b>Enable Group-Based Leaderboard</b>", richToggle, Array.Empty<GUILayoutOption>());
			GUI.color = color;
			if (flag != Plugin.UseGroupLeaderboard.Value)
			{
				Plugin.UseGroupLeaderboard.Value = flag;
				NetworkGroupSync.RequestSetGroupLeaderboard(flag);
			}
			GUILayout.Space(12f);
			GUILayout.Label("<b>Create Group</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			newGroupName = GUILayout.TextField(newGroupName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
			GUILayout.Label("Color (Skin):", richLabel, Array.Empty<GUILayoutOption>());
			newGroupSkinIndex = SkinSelector(newGroupSkinIndex);
			if (GUILayout.Button("Create Group", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) }) && !string.IsNullOrWhiteSpace(newGroupName))
			{
				Color skinColor = GetSkinColor(newGroupSkinIndex);
				NetworkGroupSync.RequestCreateGroup(newGroupName, skinColor, newGroupSkinIndex);
				newGroupName = "";
			}
			GUILayout.Space(15f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(270f),
				GUILayout.ExpandHeight(true)
			});
			GUILayout.Label("<b>Groups</b>", headerLabel, Array.Empty<GUILayoutOption>());
			scrollGroups = GUILayout.BeginScrollView(scrollGroups, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			DrawGroupList();
			GUILayout.EndScrollView();
			GUILayout.Space(12f);
			GUILayout.EndVertical();
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(270f),
				GUILayout.ExpandHeight(true)
			});
			GUILayout.Label("<b>Players</b>", headerLabel, Array.Empty<GUILayoutOption>());
			DrawGroupDropdown();
			scrollPlayers = GUILayout.BeginScrollView(scrollPlayers, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			EnsurePlayerCache();
			for (int i = 0; i < cachedCharacters.Count; i++)
			{
				Character val = cachedCharacters[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((MonoBehaviourPun)val).photonView == (Object)null) && ((MonoBehaviourPun)val).photonView.Owner != null)
				{
					Player owner = ((MonoBehaviourPun)val).photonView.Owner;
					int actorNumber = owner.ActorNumber;
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label(owner.NickName + " (" + actorNumber + ")", Array.Empty<GUILayoutOption>());
					if (GUILayout.Button("Add", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
					{
						string groupNameByIndex = GetGroupNameByIndex(selectedGroupIndex);
						NetworkGroupSync.RequestAssignPlayer(actorNumber, groupNameByIndex);
					}
					GUILayout.EndHorizontal();
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(12f);
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
			HandleAutoScroll();
		}

		private void HandleAutoScroll()
		{
			//IL_0027: 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)
			if (autoScrollTargetIndex >= 0)
			{
				float num = 110f;
				float num2 = (float)autoScrollTargetIndex * (num + 5f);
				scrollGroups = new Vector2(0f, num2);
				autoScrollTargetIndex = -1;
			}
		}

		private void DrawGroupList()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			string text = null;
			int? num = null;
			foreach (KeyValuePair<string, Group> group in GroupManager.Groups)
			{
				Group value = group.Value;
				GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
				GUILayout.Label("<b>" + value.Name + "</b>", headerLabel, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Color (Skin):", richLabel, Array.Empty<GUILayoutOption>());
				int num2 = SkinSelector(value.SkinIndex);
				if (num2 != value.SkinIndex)
				{
					value.SkinIndex = num2;
					Color skinColor = GetSkinColor(num2);
					NetworkGroupSync.RequestSetGroupColor(value.Name, skinColor, num2);
				}
				GUILayout.Space(5f);
				GUILayout.Label("Members:", richLabel, Array.Empty<GUILayoutOption>());
				foreach (int item in GroupManager.BuildMemberLists()[value.Name])
				{
					Room currentRoom = PhotonNetwork.CurrentRoom;
					Player val = ((currentRoom != null) ? currentRoom.GetPlayer(item, false) : null);
					string arg = ((val != null) ? val.NickName : $"Player {item}");
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"{arg} ({item})", Array.Empty<GUILayoutOption>());
					if (GUILayout.Button("Remove", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
					{
						num = item;
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.Space(5f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				if (!GroupManager.IsSpectatorGroup(value.Name) && GUILayout.Button("Delete Group", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
				{
					text = value.Name;
				}
				GUILayout.EndHorizontal();
				GUILayout.EndVertical();
				GUILayout.Space(5f);
			}
			if (num.HasValue)
			{
				NetworkGroupSync.RequestAssignPlayer(num.Value, "Ungrouped");
			}
			if (text == null)
			{
				return;
			}
			List<int> list = new List<int>(GroupManager.BuildMemberLists()[text]);
			foreach (int item2 in list)
			{
				NetworkGroupSync.RequestAssignPlayer(item2, "Ungrouped");
			}
			ReviveTokenManager.DeleteGroupToken(text);
			NetworkGroupSync.RequestDeleteGroup(text);
		}

		private void DrawHostToolsTab()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>Host Tools</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			scrollPlayers = GUILayout.BeginScrollView(scrollPlayers, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			EnsurePlayerCache();
			List<Character> list = cachedCharacters;
			string[] array = cachedPlayerNames;
			GUILayout.Label("<b>Select Player</b>", headerLabel, Array.Empty<GUILayoutOption>());
			if (array.Length == 0)
			{
				GUILayout.Label("No players found.", richLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndScrollView();
				return;
			}
			if (selectedHostPlayerIndex < 0 || selectedHostPlayerIndex >= array.Length)
			{
				selectedHostPlayerIndex = 0;
			}
			if (selectedHostPlayerIndex >= list.Count)
			{
				selectedHostPlayerIndex = 0;
			}
			if (GUILayout.Button("Player: " + array[selectedHostPlayerIndex], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) }))
			{
				hostPlayerDropdownOpen = !hostPlayerDropdownOpen;
			}
			if (hostPlayerDropdownOpen)
			{
				GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
				for (int i = 0; i < array.Length; i++)
				{
					if (GUILayout.Button(array[i], Array.Empty<GUILayoutOption>()))
					{
						selectedHostPlayerIndex = i;
						hostPlayerDropdownOpen = false;
					}
				}
				GUILayout.EndVertical();
			}
			GUILayout.Space(10f);
			if (selectedHostPlayerIndex < 0 || selectedHostPlayerIndex >= list.Count)
			{
				selectedHostPlayerIndex = 0;
			}
			int ownerActorNr = ((MonoBehaviourPun)list[selectedHostPlayerIndex]).photonView.OwnerActorNr;
			Character val = GetRealCharacter(ownerActorNr);
			if ((Object)(object)val == (Object)null)
			{
				val = list[selectedHostPlayerIndex];
			}
			if ((Object)(object)val == (Object)null || (Object)(object)((MonoBehaviourPun)val).photonView == (Object)null || ((MonoBehaviourPun)val).photonView.Owner == null)
			{
				GUILayout.Label("Player not ready.", richLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndScrollView();
				return;
			}
			bool flag = (Object)(object)val.data != (Object)null && val.data.dead;
			GUILayout.Space(20f);
			GUILayout.Label("<b>Player Management</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			if (flag)
			{
				if (GUILayout.Button("Revive", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					RevivePlayer(val);
				}
			}
			else
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("To Player", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					TeleportToPlayer(val);
				}
				if (GUILayout.Button("Player To Me", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					TeleportPlayerToMe(val);
				}
				GUILayout.EndHorizontal();
				if (GUILayout.Button("To Biome End", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					TeleportPlayerToBiomeEnd(val);
				}
				if ((Object)(object)Singleton<MapHandler>.Instance != (Object)null && GUILayout.Button("Revive", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					RevivePlayer(val);
				}
			}
			GUILayout.Space(20f);
			GUILayout.Label("<b>Leaderboard Flags</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			if (!Leaderboard.TryGetStats(ownerActorNr, out var _))
			{
				GUILayout.Label("No stats found for this player.", richLabel, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Add DNF", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					Character characterByActor = Leaderboard.GetCharacterByActor(ownerActorNr);
					if (characterByActor != null)
					{
						Leaderboard.MarkDNF(characterByActor);
					}
				}
				if (GUILayout.Button("Remove DNF", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					Character characterByActor2 = Leaderboard.GetCharacterByActor(ownerActorNr);
					if (characterByActor2 != null)
					{
						Leaderboard.ClearDNF(characterByActor2);
					}
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(20f);
			GUILayout.Label("<b>Global Revive</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			if (GUILayout.Button("Revive All Players", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				ReviveAllPlayers();
			}
			GUILayout.Space(20f);
			GUILayout.Label("<b>Group Management</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			EnsureGroupCache();
			string[] array2 = cachedGroupNames;
			if (selectedHostGroupIndex < 0 || selectedHostGroupIndex >= array2.Length)
			{
				selectedHostGroupIndex = 0;
				hostGroupDropdownOpen = false;
			}
			if (array2.Length == 0)
			{
				GUILayout.Label("No groups created.", richLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndScrollView();
				return;
			}
			if (GUILayout.Button("Group: " + array2[selectedHostGroupIndex], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) }))
			{
				hostGroupDropdownOpen = !hostGroupDropdownOpen;
			}
			if (hostGroupDropdownOpen)
			{
				GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
				for (int j = 0; j < array2.Length; j++)
				{
					if (GUILayout.Button(array2[j], Array.Empty<GUILayoutOption>()))
					{
						selectedHostGroupIndex = j;
						hostGroupDropdownOpen = false;
					}
				}
				GUILayout.EndVertical();
			}
			GUILayout.Space(10f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Give Token", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				ReviveTokenManager.AddToken(array2[selectedHostGroupIndex]);
			}
			if (GUILayout.Button("Remove Token", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				ReviveTokenManager.RemoveToken(array2[selectedHostGroupIndex]);
			}
			GUILayout.EndHorizontal();
			GUILayout.EndScrollView();
		}

		private void TeleportToPlayer(Character target)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = GetLocalCharacter();
			if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)target == (Object)null))
			{
				Vector3 val = target.Center + Vector3.right * 2f;
				localCharacter.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, true });
			}
		}

		private void TeleportPlayerToMe(Character target)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = GetLocalCharacter();
			if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)target == (Object)null))
			{
				Vector3 val = localCharacter.Center + Vector3.right * 2f;
				target.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, true });
			}
		}

		private void TeleportPlayerToBiomeEnd(Character target)
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector3 currentBiomeEndPosition = Patch_Biome.CurrentBiomeEndPosition;
			if (!((Object)(object)target == (Object)null) && !(currentBiomeEndPosition == Vector3.zero))
			{
				target.refs.view.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2]
				{
					currentBiomeEndPosition + Vector3.right * 1.5f,
					true
				});
			}
		}

		private void RevivePlayer(Character target)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0062: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected I4, but got Unknown
			//IL_0120: 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_012f: 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_0139: 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_0105: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = GetLocalCharacter();
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)target == (Object)null || ((Object)(object)target.data != (Object)null && !target.data.dead))
			{
				return;
			}
			Vector3 zero = Vector3.zero;
			int ownerActorNr = ((MonoBehaviourPun)target).photonView.OwnerActorNr;
			if (SkeletonTracker.TryGetSkeleton(ownerActorNr, out var skeleton))
			{
				zero = SkeletonTracker.GetSkeletonPosition(skeleton) + Vector3.up * 1f;
			}
			else
			{
				string groupOfPlayer = GroupManager.GetGroupOfPlayer(ownerActorNr);
				Character val = null;
				foreach (Character allPlayerCharacter in PlayerHandler.GetAllPlayerCharacters())
				{
					if (!((Object)(object)allPlayerCharacter == (Object)null) && !allPlayerCharacter.data.dead && !(GroupManager.GetGroupOfPlayer(((MonoBehaviourPun)allPlayerCharacter).photonView.OwnerActorNr) != groupOfPlayer))
					{
						val = allPlayerCharacter;
						break;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					zero = ((Component)val.refs.movement).transform.position + Vector3.up * 1f;
				}
				else
				{
					zero = localCharacter.Center + Vector3.up * 1f;
					if (localCharacter.data.dead)
					{
						Character val2 = null;
						foreach (Character allPlayerCharacter2 in PlayerHandler.GetAllPlayerCharacters())
						{
							if ((Object)(object)allPlayerCharacter2 != (Object)null && !allPlayerCharacter2.data.dead)
							{
								val2 = allPlayerCharacter2;
								break;
							}
						}
						if ((Object)(object)val2 != (Object)null)
						{
							zero = ((Component)val2.refs.movement).transform.position + Vector3.up * 1f;
						}
					}
				}
			}
			((MonoBehaviourPun)target).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3]
			{
				zero,
				true,
				(int)MapHandler.CurrentSegmentNumber
			});
			ReviveNetwork.InstanceView.RPC("RPC_SinnerPeak_DestroySkeleton", (RpcTarget)0, new object[1] { ownerActorNr });
		}

		private void ReviveAllPlayers()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected I4, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			RespawnChest val = Object.FindAnyObjectByType<RespawnChest>();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[SinnerPeak] No RespawnChest found in scene.");
				return;
			}
			Vector3 val2 = ((Component)val).transform.position + ((Component)val).transform.up * 6f;
			int num = (int)val.SegmentNumber;
			Plugin.Log.LogInfo((object)"[SinnerPeak] Global Revive triggered.");
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter.data == (Object)null) && (allCharacter.data.dead || allCharacter.data.fullyPassedOut))
				{
					Vector3 onUnitSphere = Random.onUnitSphere;
					Vector3 val3 = val2 + onUnitSphere;
					((MonoBehaviourPun)allCharacter).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { val3, true, num });
				}
			}
		}

		private void DrawModdedPlayersTab()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: 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_030c: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>Players</b>", headerLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				GUILayout.Label("Not in a room.", richLabel, Array.Empty<GUILayoutOption>());
				return;
			}
			EnsurePlayerCache();
			List<Character> list = cachedCharacters;
			if (list == null || list.Count == 0)
			{
				GUILayout.Label("No players found.", richLabel, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			scrollPlayers = GUILayout.BeginScrollView(scrollPlayers, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			foreach (Character cachedCharacter in cachedCharacters)
			{
				if ((Object)(object)cachedCharacter == (Object)null || (Object)(object)((MonoBehaviourPun)cachedCharacter).photonView == (Object)null || ((MonoBehaviourPun)cachedCharacter).photonView.Owner == null)
				{
					continue;
				}
				Player owner = ((MonoBehaviourPun)cachedCharacter).photonView.Owner;
				int actorNumber = owner.ActorNumber;
				string text = $"{owner.NickName} ({actorNumber})";
				string text2 = (ModdedClientRegistry.IsModded(actorNumber) ? "<color=green><b>MODDED</b></color>" : "<color=yellow><b>VANILLA</b></color>");
				GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(240f) });
				GUILayout.Label(text2, richLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
				GUILayout.EndHorizontal();
				CharacterData data = cachedCharacter.data;
				if ((Object)(object)data == (Object)null)
				{
					GUILayout.Label("Stamina: <i>loading...</i>", richLabel, Array.Empty<GUILayoutOption>());
					GUILayout.EndVertical();
					continue;
				}
				float stamina = Mathf.Clamp01(data.currentStamina);
				GUILayout.Label("Stamina:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
				DrawStaminaBar(stamina);
				Player player = PlayerHandler.GetPlayer(actorNumber);
				if ((Object)(object)player != (Object)null)
				{
					GUILayout.Space(5f);
					GUILayout.Label("Items:", richLabel, Array.Empty<GUILayoutOption>());
					List<(string, Item)> playerItemsFlat = GetPlayerItemsFlat(player);
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					foreach (var (text3, val) in playerItemsFlat)
					{
						if ((Object)(object)val == (Object)null)
						{
							if (GUILayout.Button((Texture)(object)Texture2D.grayTexture, (GUILayoutOption[])(object)new GUILayoutOption[2]
							{
								GUILayout.Width(48f),
								GUILayout.Height(48f)
							}))
							{
								giveItemPopupOpen = true;
								giveItemTargetActor = actorNumber;
								giveItemSlotLabel = text3;
							}
							Rect lastRect = GUILayoutUtility.GetLastRect();
							if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition))
							{
								GUI.Label(new Rect(Event.current.mousePosition.x + 15f, Event.current.mousePosition.y + 15f, 200f, 40f), text3 + ": Click to give item", richLabel);
							}
						}
						else
						{
							ItemUIData uIData = val.UIData;
							string arg = ((uIData != null) ? uIData.itemName : ((Object)val).name);
							DrawItemIconWithTooltip(GetItemIcon(val), $"{text3}: {arg}\nID: {val.itemID}");
						}
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.EndVertical();
			}
			GUILayout.Space(20f);
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawGiveItemPopup(int id)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>Select an item to give</b>", richLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			giveItemScroll = GUILayout.BeginScrollView(giveItemScroll, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(280f),
				GUILayout.Height(300f)
			});
			EnsureGiveItemList();
			foreach (var dynamicGiveItem in dynamicGiveItemList)
			{
				if (GUILayout.Button(dynamicGiveItem.name, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					NetworkGiveItem(giveItemTargetActor, dynamicGiveItem.id);
					giveItemPopupOpen = false;
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(10f);
			if (GUILayout.Button("Cancel", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) }))
			{
				giveItemPopupOpen = false;
			}
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private Character GetLocalCharacter()
		{
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				return null;
			}
			int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber;
			Character result = default(Character);
			if (PlayerHandler.TryGetCharacter(actorNumber, ref result))
			{
				return result;
			}
			return null;
		}

		private void EnsureSkinStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (skinButtonStyle == null)
			{
				skinButtonStyle = new GUIStyle(GUI.skin.button);
				skinButtonSelectedStyle = new GUIStyle(GUI.skin.button);
				Texture2D background = GUI.skin.button.hover.background;
				skinButtonSelectedStyle.normal.background = background;
				skinButtonSelectedStyle.hover.background = background;
				skinButtonSelectedStyle.active.background = background;
				skinButtonSelectedStyle.focused.background = background;
			}
		}

		private int SkinSelector(int currentIndex)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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)
			EnsureSkinStyles();
			if ((Object)(object)Singleton<Customization>.Instance == (Object)null || Singleton<Customization>.Instance.skins == null || Singleton<Customization>.Instance.skins.Length == 0)
			{
				GUILayout.Label("Skins not loaded yet.", richLabel, Array.Empty<GUILayoutOption>());
				return currentIndex;
			}
			CustomizationOption[] skins = Singleton<Customization>.Instance.skins;
			int num = skins.Length;
			int num2 = 6;
			int num3 = Mathf.CeilToInt((float)num / (float)num2);
			int num4 = currentIndex;
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < num3; i++)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				for (int j = 0; j < num2; j++)
				{
					int num5 = i * num2 + j;
					if (num5 >= num)
					{
						break;
					}
					Color color = skins[num5].color;
					GUI.color = color;
					GUIStyle val = ((num5 == num4) ? skinButtonSelectedStyle : skinButtonStyle);
					if (GUILayout.Button("", val, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(25f),
						GUILayout.Height(25f)
					}))
					{
						num4 = num5;
					}
					GUI.color = Color.white;
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
			return num4;
		}

		private Color GetSkinColor(int index)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return Singleton<Customization>.Instance.skins[index].color;
		}

		private void DrawGroupDropdown()
		{
			EnsureGroupCache();
			string[] array = cachedGroupNames;
			if (array.Length == 0)
			{
				GUILayout.Label("No groups created.", richLabel, Array.Empty<GUILayoutOption>());
				return;
			}
			if (selectedGroupIndex >= array.Length)
			{
				selectedGroupIndex = 0;
			}
			if (GUILayout.Button("Assign to: " + array[selectedGroupIndex], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) }))
			{
				dropdownOpen = !dropdownOpen;
			}
			if (!dropdownOpen)
			{
				return;
			}
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < array.Length; i++)
			{
				if (GUILayout.Button(array[i], Array.Empty<GUILayoutOption>()))
				{
					selectedGroupIndex = i;
					dropdownOpen = false;
					autoScrollTargetIndex = i;
				}
			}
			GUILayout.EndVertical();
		}

		private string[] GetGroupNames()
		{
			EnsureGroupCache();
			return cachedGroupNames;
		}

		private string GetGroupNameByIndex(int index)
		{
			EnsureGroupCache();
			if (index < 0 || index >= cachedGroupNames.Length)
			{
				return "Ungrouped";
			}
			return cachedGroupNames[index];
		}

		private void ForceRefreshPlayerCache()
		{
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				cachedCharacters.Clear();
				cachedPlayerNames = Array.Empty<string>();
				nextPlayerCacheTime = Time.time + 3f;
				return;
			}
			cachedCharacters = PlayerHandler.GetAllPlayerCharacters() ?? new List<Character>();
			int count = cachedCharacters.Count;
			cachedPlayerNames = new string[count];
			for (int i = 0; i < count; i++)
			{
				Character val = cachedCharacters[i];
				if ((Object)(object)val == (Object)null || (Object)(object)((MonoBehaviourPun)val).photonView == (Object)null || ((MonoBehaviourPun)val).photonView.Owner == null)
				{
					cachedPlayerNames[i] = "Unknown";
					continue;
				}
				Player owner = ((MonoBehaviourPun)val).photonView.Owner;
				cachedPlayerNames[i] = owner.NickName + " (" + owner.ActorNumber + ")";
			}
			nextPlayerCacheTime = Time.time + 3f;
		}

		private void ForceRefreshGroupCache()
		{
			Dictionary<string, Group>.KeyCollection keys = GroupManager.Groups.Keys;
			cachedGroupNames = new string[keys.Count];
			int num = 0;
			foreach (string item in keys)
			{
				cachedGroupNames[num++] = item;
			}
			lastGroupCount = cachedGroupNames.Length;
			groupCacheInitialized = true;
		}

		private void DrawStaminaBar(float stamina, float width = 120f, float height = 14f)
		{
			//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_0008: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0041: 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_007f: 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)
			Rect rect = GUILayoutUtility.GetRect(width, height);
			GUI.color = Color.black;
			GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
			Color color = ((!(stamina > 0.5f)) ? Color.Lerp(Color.red, Color.yellow, stamina * 2f) : Color.Lerp(Color.yellow, Color.green, (stamina - 0.5f) * 2f));
			GUI.color = color;
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width * stamina, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
		}

		private void DrawItemIconWithTooltip(Texture2D icon, string tooltip, float size = 48f)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(size) });
			GUILayout.Button((Texture)(object)icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(size),
				GUILayout.Height(size)
			});
			Rect lastRect = GUILayoutUtility.GetLastRect();
			if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition))
			{
				GUI.Label(new Rect(Event.current.mousePosition.x + 15f, Event.current.mousePosition.y + 15f, 250f, 60f), tooltip, richLabel);
			}
			GUILayout.EndVertical();
		}

		private Texture2D GetItemIcon(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return Texture2D.grayTexture;
			}
			ItemUIData uIData = item.UIData;
			if (uIData == null)
			{
				return Texture2D.grayTexture;
			}
			Texture2D icon = uIData.GetIcon();
			if (!((Object)(object)icon != (Object)null))
			{
				return Texture2D.grayTexture;
			}
			return icon;
		}

		private List<(string label, Item item)> GetPlayerItemsFlat(Player p)
		{
			List<(string, Item)> list = new List<(string, Item)>();
			for (int i = 0; i < p.itemSlots.Length; i++)
			{
				ItemSlot val = p.itemSlots[i];
				list.Add(($"S{i}", val.IsEmpty() ? null : val.prefab));
			}
			if (p.backpackSlot.hasBackpack)
			{
				Item val2 = ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects.Find((Item val3) => ((Object)val3).name == "Backpack");
				Texture2D icon = (((Object)(object)val2 != (Object)null && val2.UIData != null) ? val2.UIData.GetIcon() : Texture2D.grayTexture);
				DrawItemIconWithTooltip(icon, "B: Backpack");
			}
			else
			{
				DrawItemIconWithTooltip(Texture2D.grayTexture, "B: Empty");
			}
			return list;
		}

		private void NetworkGiveItem(int actor, ushort itemID)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Character realCharacter = GetRealCharacter(actor);
			if ((Object)(object)realCharacter == (Object)null)
			{
				return;
			}
			Player player = realCharacter.player;
			if (!((Object)(object)player == (Object)null))
			{
				ItemInstanceData val = new ItemInstanceData(Guid.NewGuid());
				ItemInstanceDataHandler.AddInstanceData(val);
				ItemSlot val2 = default(ItemSlot);
				if (!player.AddItem(itemID, val, ref val2))
				{
					Debug.LogWarning((object)$"[SinnerPeak] Failed to give item {itemID} to player {actor}");
				}
			}
		}

		private void EnsureGiveItemList()
		{
			if (giveItemListInitialized)
			{
				return;
			}
			dynamicGiveItemList.Clear();
			foreach (Item @object in ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects)
			{
				if (!((Object)(object)@object == (Object)null) && @object.itemID != 0)
				{
					string item = ((@object.UIData != null && !string.IsNullOrEmpty(@object.UIData.itemName)) ? @object.UIData.itemName : ((Object)@object).name);
					dynamicGiveItemList.Add((item, @object.itemID));
				}
			}
			dynamicGiveItemList.Sort(((string name, ushort id) a, (string name, ushort id) b) => string.Compare(a.name, b.name, StringComparison.OrdinalIgnoreCase));
			giveItemListInitialized = true;
		}

		public override void OnPlayerLeftRoom(Player otherPlayer)
		{
			ForceRefreshPlayerCache();
			ClampHostPlayerIndex();
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			ForceRefreshPlayerCache();
			ClampHostPlayerIndex();
		}

		private void ClampHostPlayerIndex()
		{
			int num = Mathf.Min(cachedCharacters.Count, cachedPlayerNames.Length);
			if (num == 0)
			{
				selectedHostPlayerIndex = 0;
			}
			else if (selectedHostPlayerIndex < 0 || selectedHostPlayerIndex >= num)
			{
				selectedHostPlayerIndex = 0;
			}
		}
	}
	public class LeaderboardUI : MonoBehaviour
	{
		private const float MIN_WIDTH = 300f;

		private const float MAX_WIDTH = 600f;

		private Rect windowRect = new Rect(50f, 50f, 450f, 600f);

		private GUIStyle windowStyle;

		private GUIStyle labelStyle;

		private GUIStyle titleStyle;

		private static readonly GUIContent tempContent = new GUIContent();

		private bool stylesReady;

		private float nextWidthRecalcTime;

		private float cachedContentWidth = 300f;

		private Canvas tmpCanvas;

		private RectTransform tmpPanel;

		private TextMeshProUGUI tmpTitle;

		private ScrollRect tmpScrollRect;

		private RectTransform tmpViewport;

		private RectTransform tmpContent;

		private TMP_FontAsset darumaFont;

		private readonly List<TextMeshProUGUI> tmpEntries = new List<TextMeshProUGUI>();

		private bool tmpInitialized;

		private float nextY;

		private const float lineHeight = 26f;

		public static bool UseTMPUI => Plugin.UseTMPLeaderboard.Value;

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Plugin.ToggleLeaderboardKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Plugin.ShowLeaderboard.Value = !Plugin.ShowLeaderboard.Value;
			}
			value = Plugin.TogglePointsKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Plugin.ShowPointsMode = !Plugin.ShowPointsMode;
			}
			if (UseTMPUI)
			{
				if ((Object)(object)tmpCanvas == (Object)null)
				{
					BuildTMPUI();
					tmpInitialized = false;
				}
				else if (!tmpInitialized)
				{
					tmpInitialized = true;
				}
				else
				{
					((Behaviour)tmpCanvas).enabled = Plugin.ShowLeaderboard.Value;
					UpdateTMPLeaderboard();
				}
			}
			else if ((Object)(object)tmpCanvas != (Object)null)
			{
				((Behaviour)tmpCanvas).enabled = false;
			}
		}

		private void OnGUI()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//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)
			if (Plugin.ShowLeaderboard.Value && !UseTMPUI)
			{
				if (!stylesReady)
				{
					InitStyles();
				}
				windowRect = GUI.Window(69420, windowRect, Plugin.ShowPointsMode ? new WindowFunction(DrawPointsWindow) : new WindowFunction(DrawMainWindow), GUIContent.none, windowStyle);
			}
		}

		private void InitStyles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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: Expected O, but got Unknown
			windowStyle = new GUIStyle(GUI.skin.window);
			windowStyle.normal.background = Texture2D.blackTexture;
			labelStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 16,
				richText = true
			};
			titleStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 20,
				richText = true,
				alignment = (TextAnchor)4
			};
			stylesReady = true;
		}

		private void DrawMainWindow(int id)
		{
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			GUILayout.Label("<b>SinnerPeak Leaderboard</b>", titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			MountainProgressHandler instance = Singleton<MountainProgressHandler>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				GUILayout.Label("<i>Waiting for game...</i>", labelStyle, Array.Empty<GUILayoutOption>());
				GUI.DragWindow();
				return;
			}
			int maxProgressPointReached = instance.maxProgressPointReached;
			if (!Plugin.UseGroupLeaderboard.Value)
			{
				List<PlayerStats> sortedPlayers = Leaderboard.GetSortedPlayers();
				foreach (PlayerStats item in sortedPlayers)
				{
					if (item == null || GroupManager.IsSpectator(item.ActorNumber))
					{
						continue;
					}
					string text = ColorUtility.ToHtmlStringRGB(item.Color);
					string text2;
					if (item.DNF)
					{
						text2 = $"<color=#888888>{item.Name}</color> — {item.Height:F1}m <color=#FF2222><b>DNF</b></color>";
					}
					else
					{
						string arg = "<color=#" + text + ">" + item.Name + "</color>";
						text2 = $"{arg} — {item.Height:F1}m";
						if (item.LastFinishedBiome == maxProgressPointReached)
						{
							text2 += " <color=#00FF00><b>FINISHED</b></color>";
						}
					}
					GUILayout.Label(text2, labelStyle, Array.Empty<GUILayoutOption>());
					tempContent.text = text2;
					float num2 = labelStyle.CalcSize(tempContent).x + 40f;
					if (num2 > num)
					{
						num = num2;
					}
				}
			}
			else
			{
				List<Leaderboard.GroupStats> groupedLeaderboard = Leaderboard.GetGroupedLeaderboard();
				foreach (Leaderboard.GroupStats item2 in groupedLeaderboard)
				{
					if (GroupManager.IsSpectatorGroup(item2.GroupName))
					{
						continue;
					}
					string text3 = ColorUtility.ToHtmlStringRGB(item2.Color);
					bool flag = Leaderboard.HasGroupFinished(item2.GroupName, maxProgressPointReached);
					bool flag2 = Leaderboard.HasGroupDNF(item2.GroupName);
					int tokens = ReviveTokenManager.GetTokens(item2.GroupName);
					string text4 = $"<b><color=#{text3}>{item2.GroupName} ({tokens})</color></b> — Avg: {item2.AverageHeight:F1}m";
					if (flag)
					{
						text4 += " <color=#00FF00><b>FINISHED</b></color>";
					}
					else if (flag2)
					{
						text4 += " <color=#FF2222><b>DNF</b></color>";
					}
					GUILayout.Label(text4, labelStyle, Array.Empty<GUILayoutOption>());
					tempContent.text = text4;
					float num3 = labelStyle.CalcSize(tempContent).x + 40f;
					if (num3 > num)
					{
						num = num3;
					}
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Space(20f);
					GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
					foreach (PlayerStats member in item2.Members)
					{
						if (GroupManager.IsSpectator(member.ActorNumber))
						{
							continue;
						}
						string text5 = ColorUtility.ToHtmlStringRGB(member.Color);
						string text6;
						if (member.DNF)
						{
							text6 = $"<color=#888888>{member.Name}</color> — {member.Height:F1}m <color=#FF2222><b>DNF</b></color>";
						}
						else
						{
							string arg2 = "<color=#" + text5 + ">" + member.Name + "</color>";
							text6 = $"{arg2} — {member.Height:F1}m";
							if (member.LastFinishedBiome == maxProgressPointReached)
							{
								text6 += " <color=#00FF00><b>FINISHED</b></color>";
							}
						}
						GUILayout.Label(text6, labelStyle, Array.Empty<GUILayoutOption>());
					}
					GUILayout.EndVertical();
					GUILayout.EndHorizontal();
					GUILayout.Space(8f);
				}
			}
			if (Time.time >= nextWidthRecalcTime)
			{
				cachedContentWidth = Mathf.Clamp(num, 300f, 600f);
				nextWidthRecalcTime = Time.time + 2f;
			}
			((Rect)(ref windowRect)).width = cachedContentWidth;
			GUI.DragWindow();
		}

		private void DrawPointsWindow(int id)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>Total Points</b>", titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			List<PlayerStats> sortedPlayersByPoints = Leaderboard.GetSortedPlayersByPoints();
			foreach (PlayerStats item in sortedPlayersByPoints)
			{
				if (!GroupManager.IsSpectator(item.ActorNumber))
				{
					int actorNumber = item.ActorNumber;
					int value;
					int num = (Plugin.TotalPoints.TryGetValue(actorNumber, out value) ? value : 0);
					string arg = ColorUtility.ToHtmlStringRGB(item.Color);
					string text = $"<color=#{arg}>{item.Name}</color> — <color=#FFD700>{num} pts</color>";
					GUILayout.Label(text, labelStyle, Array.Empty<GUILayoutOption>());
				}
			}
			GUI.DragWindow();
		}

		private void BuildTMPUI()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_00a4: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Expected O, but got Unknown
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: 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_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Expected O, but got Unknown
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			darumaFont = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset x) => ((Object)x).name == "DarumaDropOne-Regular SDF"));
			GameObject val = new GameObject("TMP_LeaderboardCanvas");
			tmpCanvas = val.AddComponent<Canvas>();
			tmpCanvas.renderMode = (RenderMode)0;
			val.AddComponent<CanvasScaler>();
			val.AddComponent<GraphicRaycaster>();
			Object.DontDestroyOnLoad((Object)(object)val);
			GameObject val2 = new GameObject("TMP_Panel");
			tmpPanel = val2.AddComponent<RectTransform>();
			((Transform)tmpPanel).SetParent(((Component)tmpCanvas).transform, false);
			tmpPanel.anchorMin = new Vector2(0f, 1f);
			tmpPanel.anchorMax = new Vector2(0f, 1f);
			tmpPanel.pivot = new Vector2(0f, 1f);
			tmpPanel.anchoredPosition = new Vector2(120f, 5f);
			tmpPanel.sizeDelta = new Vector2(500f, 400f);
			Image val3 = val2.AddComponent<Image>();
			((Graphic)val3).color = new Color(0f, 0f, 0f, 0f);
			GameObject val4 = new GameObject("TMP_Title");
			tmpTitle = val4.AddComponent<TextMeshProUGUI>();
			((TMP_Text)tmpTitle).font = darumaFont;
			((TMP_Text)tmpTitle).fontSize = 28f;
			((TMP_Text)tmpTitle).alignment = (TextAlignmentOptions)514;
			((TMP_Text)tmpTitle).text = "SinnerPeak";
			((TMP_Text)tmpTitle).fontMaterial.SetFloat(ShaderUtilities.ID_FaceDilate, 0.15f);
			((TMP_Text)tmpTitle).fontMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, 0.12f);
			((TMP_Text)tmpTitle).fontMaterial.SetColor(ShaderUtilities.ID_OutlineColor, new Color(0f, 0f, 0f, 0.55f));
			((Transform)((TMP_Text)tmpTitle).rectTransform).SetParent((Transform)(object)tmpPanel, false);
			((TMP_Text)tmpTitle).rectTransform.anchorMin = new Vector2(0f, 1f);
			((TMP_Text)tmpTitle).rectTransform.anchorMax = new Vector2(1f, 1f);
			((TMP_Text)tmpTitle).rectTransform.pivot = new Vector2(0f, 1f);
			((TMP_Text)tmpTitle).rectTransform.sizeDelta = new Vector2(0f, 40f);
			GameObject val5 = new GameObject("TMP_ScrollRect", new Type[1] { typeof(RectTransform) });
			tmpScrollRect = val5.AddComponent<ScrollRect>();
			RectTransform component = val5.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)tmpPanel, false);
			component.anchorMin = new Vector2(0f, 0f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(0f, 1f);
			component.offsetMin = new Vector2(0f, 0f);
			component.offsetMax = new Vector2(0f, -40f);
			tmpScrollRect.horizontal = false;
			tmpScrollRect.vertical = true;
			tmpScrollRect.movementType = (MovementType)2;
			tmpScrollRect.scrollSensitivity = 20f;
			GameObject val6 = new GameObject("Viewport");
			tmpViewport = val6.AddComponent<RectTransform>();
			((Transform)tmpViewport).SetParent((Transform)(object)component, false);
			tmpViewport.anchorMin = new Vector2(0f, 0f);
			tmpViewport.anchorMax = new Vector2(1f, 1f);
			tmpViewport.pivot = new Vector2(0f, 1f);
			tmpViewport.sizeDelta = Vector2.zero;
			Image val7 = val6.AddComponent<Image>();
			((Graphic)val7).color = new Color(0f, 0f, 0f, 0f);
			Mask val8 = val6.AddComponent<Mask>();
			val8.showMaskGraphic = false;
			tmpScrollRect.viewport = tmpViewport;
			GameObject val9 = new GameObject("TMP_Content", new Type[1] { typeof(RectTransform) });
			tmpContent = val9.GetComponent<RectTransform>();
			((Transform)tmpContent).SetParent((Transform)(object)tmpPanel, false);
			tmpContent.anchorMin = new Vector2(0f, 1f);
			tmpContent.anchorMax = new Vector2(0f, 1f);
			tmpContent.pivot = new Vector2(0f, 1f);
			tmpContent.sizeDelta = new Vector2(500f, 0f);
			tmpContent.anchoredPosition = new Vector2(0f, -36f);
			Canvas.ForceUpdateCanvases();
		}

		private void UpdateTMPLeaderboard()
		{
			ClearTMPEntries();
			nextY = 0f;
			MountainProgressHandler instance = Singleton<MountainProgressHandler>.Instance;
			List<PlayerStats> sortedPlayers = Leaderboard.GetSortedPlayers();
			List<Leaderboard.GroupStats> groupedLeaderboard = Leaderboard.GetGroupedLeaderboard();
			if ((Object)(object)instance == (Object)null || (!Plugin.UseGroupLeaderboard.Value && sortedPlayers.Count == 0) || (Plugin.UseGroupLeaderboard.Value && groupedLeaderboard.Count == 0))
			{
				AddTMPEntry("Waiting for game...");
				return;
			}
			int maxProgressPointReached = instance.maxProgressPointReached;
			if (Plugin.ShowPointsMode)
			{
				UpdateTMPPoints();
			}
			else if (!Plugin.UseGroupLeaderboard.Value)
			{
				UpdateTMPIndividual(maxProgressPointReached);
			}
			else
			{
				UpdateTMPGroup(maxProgressPointReached);
			}
		}

		private void AddTMPEntry(string text, int indent = 0)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_00a5: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("TMP_Entry", new Type[1] { typeof(RectTransform) });
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = darumaFont;
			((TMP_Text)val2).fontSize = 24f;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)513;
			((TMP_Text)val2).richText = true;
			((TMP_Text)val2).text = text;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val2).fontMaterial.SetFloat(ShaderUtilities.ID_FaceDilate, 0.15f);
			((TMP_Text)val2).fontMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, 0.12f);
			((TMP_Text)val2).fontMaterial.SetColor(ShaderUtilities.ID_OutlineColor, new Color(0f, 0f, 0f, 0.55f));
			RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
			((Transform)rectTransform).SetParent((Transform)(object)tmpContent, false);
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(0f, 1f);
			rectTransform.pivot = new Vector2(0f, 1f);
			rectTransform.sizeDelta = new Vector2(500f, 26f);
			rectTransform.anchoredPosition = new Vector2((float)indent, nextY);
			nextY -= 26f;
			tmpEntries.Add(val2);
		}

		private void UpdateTMPIndividual(int currentBiomeIndex)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerStats> sortedPlayers = Leaderboard.GetSortedPlayers();
			foreach (PlayerStats item in sortedPlayers)
			{
				if (item == null || GroupManager.IsSpectator(item.ActorNumber))
				{
					continue;
				}
				string text = ColorUtility.ToHtmlStringRGB(item.Color);
				string text2;
				if (item.DNF)
				{
					string arg = "<color=#888888>" + item.Name + "</color>";
					text2 = $"{arg} — {item.Height:F1}m <color=#FF2222>DNF</color>";
				}
				else
				{
					string arg = "<color=#" + text + ">" + item.Name + "</color>";
					text2 = $"{arg} — {item.Height:F1}m";
					if (item.LastFinishedBiome == currentBiomeIndex)
					{
						text2 += " <color=#00FF00>FINISHED</color>";
					}
				}
				AddTMPEntry(text2);
			}
		}

		private void UpdateTMPGroup(int currentBiomeIndex)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			List<Leaderboard.GroupStats> groupedLeaderboard = Leaderboard.GetGroupedLeaderboard();
			foreach (Leaderboard.GroupStats item in groupedLeaderboard)
			{
				if (GroupManager.IsSpectatorGroup(item.GroupName))
				{
					continue;
				}
				string text = ColorUtility.ToHtmlStringRGB(item.Color);
				int tokens = ReviveTokenManager.GetTokens(item.GroupName);
				string text2 = $"<color=#{text}>{item.GroupName} ({tokens})</color> — Avg: {item.AverageHeight:F1}m";
				bool flag = Leaderboard.HasGroupFinished(item.GroupName, currentBiomeIndex);
				bool flag2 = Leaderboard.HasGroupDNF(item.GroupName);
				if (flag)
				{
					text2 += " <color=#00FF00>FINISHED</color>";
				}
				else if (flag2)
				{
					text2 += " <color=#FF2222>DNF</color>";
				}
				AddTMPEntry(text2);
				foreach (PlayerStats member in item.Members)
				{
					if (GroupManager.IsSpectator(member.ActorNumber))
					{
						continue;
					}
					string text3 = ColorUtility.ToHtmlStringRGB(member.Color);
					string text4;
					if (member.DNF)
					{
						string arg = "<color=#888888>" + member.Name + "</color>";
						text4 = $"{arg} — {member.Height:F1}m <color=#FF2222>DNF</color>";
					}
					else
					{
						string arg = "<color=#" + text3 + ">" + member.Name + "</color>";
						text4 = $"{arg} — {member.Height:F1}m";
						if (member.LastFinishedBiome == currentBiomeIndex)
						{
							text4 += " <color=#00FF00>FINISHED</color>";
						}
					}
					AddTMPEntry(text4, 20);
				}
			}
		}

		private void UpdateTMPPoints()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerStats> sortedPlayersByPoints = Leaderboard.GetSortedPlayersByPoints();
			foreach (PlayerStats item in sortedPlayersByPoints)
			{
				if (!GroupManager.IsSpectator(item.ActorNumber))
				{
					int actorNumber = item.ActorNumber;
					int value;
					int num = (Plugin.TotalPoints.TryGetValue(actorNumber, out value) ? value : 0);
					string text = ColorUtility.ToHtmlStringRGB(item.Color);
					string arg = "<color=#" + text + ">" + item.Name + "</color>";
					string text2 = $"{arg} — <color=#FFD700>{num} pts</color>";
					AddTMPEntry(text2);
				}
			}
		}

		private void ClearTMPEntries()
		{
			foreach (TextMeshProUGUI tmpEntry in tmpEntries)
			{
				if ((Object)(object)tmpEntry != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)tmpEntry).gameObject);
				}
			}
			tmpEntries.Clear();
		}
	}
}
namespace SinnerPeak.Revive
{
	public class ReviveBootstrap : MonoBehaviourPunCallbacks
	{
		private const int STATIC_REVIVE_VIEW_ID = 2147000000;

		private static ReviveBootstrap _instance;

		private void Awake()
		{
			if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			_instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		public override void OnJoinedRoom()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (PhotonNetwork.InRoom)
			{
				if ((Object)(object)ReviveNetwork.InstanceView == (Object)null)
				{
					GameObject val = new GameObject("SinnerPeak_ReviveNetwork");
					PhotonView val2 = val.AddComponent<PhotonView>();
					val2.ViewID = 2147000000;
					val.AddComponent<ReviveNetwork>();
					Object.DontDestroyOnLoad((Object)(object)val);
				}
				if (PhotonNetwork.IsMasterClient && (Object)(object)ReviveHostRuntime.Instance == (Object)null)
				{
					GameObject val3 = new GameObject("SinnerPeak_ReviveHostRuntime");
					val3.AddComponent<ReviveHostRuntime>();
					Object.DontDestroyOnLoad((Object)(object)val3);
				}
			}
		}

		public override void OnLeftRoom()
		{
			if ((Object)(object)ReviveNetwork.InstanceView != (Object)null)
			{
				GameObject gameObject = ((Component)ReviveNetwork.InstanceView).gameObject;
				Object.Destroy((Object)(object)gameObject);
				ReviveNetwork.InstanceView = null;
			}
			if ((Object)(object)ReviveHostRuntime.Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)ReviveHostRuntime.Instance).gameObject);
			}
		}
	}
	public static class ReviveConfig
	{
		public const float ReviveHoldSeconds = 3f;

		public const float CrouchReviveSeconds = 3f;

		public static float ReviveRadius => Plugin.ReviveRadius.Value;

		public static float ReviveRadiusSqr => ReviveRadius * ReviveRadius;

		public static int MaxTokens => Plugin.MaxTokens.Value;

		public static int StartTokens => Plugin.StartTokens.Value;

		public static KeyCode ReviveKey
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				KeyboardShortcut value = Plugin.ReviveKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}
	}
	public static class ReviveTokenManager
	{
		private static string Key(string groupName)
		{
			return "reviveTokens_" + groupName;
		}

		public static int GetTokens(string groupName)
		{
			if (string.IsNullOrWhiteSpace(groupName))
			{
				return 0;
			}
			if (PhotonNetwork.CurrentRoom != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)Key(groupName), out object value) && value is int)
			{
				return (int)value;
			}
			return 0;
		}

		private static void SetTokens(string groupName, int tokens)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (PhotonNetwork.IsMasterClient)
			{
				tokens = Mathf.Clamp(tokens, 0, ReviveConfig.MaxTokens);
				Hashtable val = new Hashtable { [(object)Key(groupName)] = tokens };
				PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
		}

		public static void AddToken(string groupName, int amount = 1)
		{
			SetTokens(groupName, GetTokens(groupName) + amount);
		}

		public static void RemoveToken(string groupName, int amount = 1)
		{
			SetTokens(groupName, Mathf.Max(0, GetTokens(groupName) - amount));
		}

		public static bool TrySpendToken(string groupName)
		{
			int tokens = GetTokens(groupName);
			if (tokens <= 0)
			{
				return false;
			}
			SetTokens(groupName, tokens - 1);
			return true;
		}

		public static void EnsureGroupTokenExists(string groupName)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null)
			{
				string text = Key(groupName);
				if (!((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)text))
				{
					Hashtable val = new Hashtable { [(object)text] = ReviveConfig.StartTokens };
					PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				}
			}
		}

		public static void DeleteGroupToken(string groupName)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null)
			{
				string text = Key(groupName);
				if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)text))
				{
					Hashtable val = new Hashtable { [(object)text] = null };
					PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				}
			}
		}
	}
	public static class SkeletonTracker
	{
		private static readonly Dictionary<int, GameObject> _skeletonByActor = new Dictionary<int, GameObject>(16);

		public static IEnumerable<KeyValuePair<int, GameObject>> AllSkeletons => _skeletonByActor;

		public static Vector3 GetSkeletonPosition(GameObject skeleton)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)skeleton == (Object)null)
			{
				return Vector3.zero;
			}
			Skelleton component = skeleton.GetComponent<Skelleton>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.hip != (Object)null)
			{
				return component.hip.position;
			}
			return skeleton.transform.position;
		}

		public static void RegisterSkeleton(int actorNumber, GameObject skeleton)
		{
			if ((Object)(object)skeleton != (Object)null)
			{
				_skeletonByActor[actorNumber] = skeleton;
			}
		}

		public static void UnregisterSkeleton(int actorNumber)
		{
			_skeletonByActor.Remove(actorNumber);
		}

		public static bool TryGetSkeleton(int actor, out GameObject skeleton)
		{
			return _skeletonByActor.TryGetValue(actor, out skeleton);
		}
	}
	[HarmonyPatch(typeof(Skelleton), "SpawnSkelly")]
	public static class Patch_Skelleton_SpawnSkelly
	{
		private static void Postfix(Skelleton __instance, Character __0)
		{
			int ownerActorNr = ((MonoBehaviourPun)__0).photonView.OwnerActorNr;
			SkeletonTracker.RegisterSkeleton(ownerActorNr, ((Component)__instance).gameObject);
		}
	}
	[HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")]
	public static class Patch_Character_ReviveCleanup
	{
		private static void Postfix(Character __instance)
		{
			if (!((Object)(object)((__instance != null) ? ((MonoBehaviourPun)__instance).photonView : null) == (Object)null))
			{
				SkeletonTracker.UnregisterSkeleton(((MonoBehaviourPun)__instance).photonView.OwnerActorNr);
			}
		}
	}
	public static class PhotonUtil
	{
		public static string GetNick(int actorNumber)
		{
			if (PhotonNetwork.CurrentRoom == null)
			{
				return $"Player {actorNumber}";
			}
			if (PhotonNetwork.CurrentRoom.Players.TryGetValue(actorNumber, out var value))
			{
				if (!string.IsNullOrWhiteSpace(value.NickName))
				{
					return value.NickName;
				}
				return $"Player {actorNumber}";
			}
			return $"Player {actorNumber}";
		}
	}
	public static class ReviveManager
	{
		private static readonly Dictionary<int, float> _crouchTimers = new Dictionary<int, float>(16);

		public static void ResetCrouchTimer(int actor)
		{
			_crouchTimers[actor] = 0f;
		}

		public static void AddCrouchTime(int actor, float dt)
		{
			if (!_crouchTimers.ContainsKey(actor))
			{
				_crouchTimers[actor] = 0f;
			}
			_crouchTimers[actor] += dt;
		}

		public static float GetCrouchTime(int actor)
		{
			if (!_crouchTimers.TryGetValue(actor, out var value))
			{
				return 0f;
			}
			return value;
		}

		public static void TryReviveFromHost(int reviverActor)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Character realCharacter = GetRealCharacter(reviverActor);
			if ((Object)(object)realCharacter == (Object)null)
			{
				return;
			}
			string groupOfPlayer = GroupManager.GetGroupOfPlayer(reviverActor);
			if (string.IsNullOrEmpty(groupOfPlayer) || GroupManager.IsSpectatorGroup(groupOfPlayer) || ReviveTokenManager.GetTokens(groupOfPlayer) <= 0)
			{
				return;
			}
			Vector3 center = realCharacter.Center;
			int num = -1;
			float num2 = float.MaxValue;
			foreach (KeyValuePair<int, GameObject> allSkeleton in SkeletonTracker.AllSkeletons)
			{
				int key = allSkeleton.Key;
				GameObject value = allSkeleton.Value;
				if (!((Object)(object)value == (Object)null) && !(GroupManager.GetGroupOfPlayer(key) != groupOfPlayer))
				{
					Vector3 val = center - SkeletonTracker.GetSkeletonPosition(value);
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num2 && sqrMagnitude <= ReviveConfig.ReviveRadiusSqr)
					{
						num2 = sqrMagnitude;
						num = key;
					}
				}
			}
			if (num == -1 || !ReviveTokenManager.TrySpendToken(groupOfPlayer))
			{
				return;
			}
			Character val2 = GetRealCharacter(num);
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = FindCharacter(num);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				string characterName = realCharacter.characterName;
				string characterName2 = val2.characterName;
				int num3 = ((!((Object)(object)Singleton<MapHandler>.Instance != (Object)null)) ? (-1) : ((int)MapHandler.CurrentSegmentNumber));
				((MonoBehaviourPun)val2).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { center, true, num3 });
				Leaderboard.ClearDNF(val2);
				if (SkeletonTracker.TryGetSkeleton(num, out var skeleton))
				{
					Object.Destroy((Object)(object)skeleton);
					SkeletonTracker.UnregisterSkeleton(num);
				}
				string message = "[Revive] Revive complete: " + characterName2 + " revived by " + characterName;
				Webhook.Send(message);
			}
		}

		private static Character FindCharacter(int actor)
		{
			List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
			for (int i = 0; i < allPlayerCharacters.Count; i++)
			{
				Character val = allPlayerCharacters[i];
				if ((Object)(object)val != (Object)null && ((MonoBehaviourPun)val).photonView.OwnerActorNr == actor)
				{
					return val;
				}
			}
			return null;
		}

		private static Character GetRealCharacter(int actor)
		{
			Character result = null;
			List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
			for (int i = 0; i < allPlayerCharacters.Count; i++)
			{
				Character val = allPlayerCharacters[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((MonoBehaviourPun)val).photonView == (Object)null) && ((MonoBehaviourPun)val).photonView.OwnerActorNr == actor && (!((Object)(object)val.data != (Object)null) || !val.data.dead))
				{
					result = val;
					break;
				}
			}
			return result;
		}
	}
	public class ReviveHostRuntime : MonoBehaviour
	{
		private const float TICK_RATE = 0.25f;

		private float _nextTick;

		private readonly List<Character> _cachedPlayers = new List<Character>(16);

		private readonly List<KeyValuePair<int, GameObject>> _cachedSkeletons = new List<KeyValuePair<int, GameObject>>(16);

		private readonly Dictionary<int, string> _groupCache = new Dictionary<int, string>(16);

		public static ReviveHostRuntime Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			GroupManager.OnPlayerGroupChanged += HandleGroupChanged;
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				GroupManager.OnPlayerGroupChanged -= HandleGroupChanged;
				Instance = null;
			}
		}

		private void HandleGroupChanged(int actor, string newGroup)
		{
			_groupCache.Clear();
		}

		private void Update()
		{
			if (PhotonNetwork.IsMasterClient && !(Time.time < _nextTick))
			{
				_nextTick = Time.time + 0.25f;
				RefreshPlayers();
				RefreshSkeletons();
				if (_cachedSkeletons.Count != 0)
				{
					RunReviveScan();
				}
			}
		}

		private void RefreshPlayers()
		{
			_cachedPlayers.Clear();
			List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
			for (int i = 0; i < allPlayerCharacters.Count; i++)
			{
				_cachedPlayers.Add(allPlayerCharacters[i]);
			}
		}

		private void RefreshSkeletons()
		{
			_cachedSkeletons.Clear();
			foreach (KeyValuePair<int, GameObject> allSkeleton in SkeletonTracker.AllSkeletons)
			{
				_cachedSkeletons.Add(allSkeleton);
			}
		}

		private string GetGroupCached(int actor)
		{
			if (_groupCache.TryGetValue(actor, out var value))
			{
				return value;
			}
			value = GroupManager.GetGroupOfPlayer(actor);
			_groupCache[actor] = value;
			return value;
		}

		public void ClearGroupCache()
		{
			_groupCache.Clear();
		}

		private void RunReviveScan()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _cachedSkeletons.Count; i++)
			{
				KeyValuePair<int, GameObject> keyValuePair = _cachedSkeletons[i];
				int key = keyValuePair.Key;
				GameObject skeleton = keyValuePair.Value;
				if ((Object)(object)skeleton == (Object)null && (!SkeletonTracker.TryGetSkeleton(key, out skeleton) || (Object)(object)skeleton == (Object)null))
				{
					continue;
				}
				string groupCached = GetGroupCached(key);
				if (string.IsNullOrEmpty(groupCached) || GroupManager.IsSpectatorGroup(groupCached) || ReviveTokenManager.GetTokens(groupCached) <= 0)
				{
					continue;
				}
				Vector3 skeletonPosition = SkeletonTracker.GetSkeletonPosition(skeleton);
				for (int j = 0; j < _cachedPlayers.Count; j++)
				{
					Character val = _cachedPlayers[j];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					CharacterData data = val.data;
					if (data.dead || data.fullyPassedOut)
					{
						continue;
					}
					int ownerActorNr = ((MonoBehaviourPun)val).photonView.OwnerActorNr;
					if (GetGroupCached(ownerActorNr) != groupCached)
					{
						continue;
					}
					Vector3 center = val.Center;
					Vector3 val2 = center - skeletonPosition;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude > ReviveConfig.ReviveRadiusSqr)
					{
						ReviveManager.ResetCrouchTimer(ownerActorNr);
						continue;
					}
					if (!data.isCrouching)
					{
						ReviveManager.ResetCrouchTimer(ownerActorNr);
						continue;
					}
					ReviveManager.AddCrouchTime(ownerActorNr, 0.25f);
					float crouchTime = ReviveManager.GetCrouchTime(ownerActorNr);
					if (crouchTime >= 3f)
					{
						Plugin.Log.LogInfo((object)("[Revive] " + val.characterName + ": CROUCH REVIVE TRIGGERED"));
						ReviveManager.ResetCrouchTimer(ownerActorNr);
						ReviveManager.TryReviveFromHost(ownerActorNr);
					}
				}
			}
		}
	}
	public class ReviveNetwork : MonoBehaviourPun
	{
		public static PhotonView InstanceView;

		private void Awake()
		{
			InstanceView = ((Component)this).GetComponent<PhotonView>();
		}

		[PunRPC]
		public void RPC_SinnerPeak_RequestRevive(int reviverActor)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				ReviveManager.TryReviveFromHost(reviverActor);
			}
		}

		[PunRPC]
		public void RPC_SinnerPeak_ShowRevivePrompt(string msg)
		{
			if (!((Object)(object)GUIManager.instance == (Object)null))
			{
				((TMP_Text)GUIManager.instance.interactPromptText).text = msg;
				if (!string.IsNullOrEmpty(msg))
				{
					GUIManager.instance.interactName.SetActive(true);
					GUIManager.instance.interactPromptPrimary.SetActive(false);
					GUIManager.instance.interactPromptSecondary.SetActive(false);
					GUIManager.instance.interactPromptHold.SetActive(false);
				}
			}
		}
	}
	public class ReviveRuntime : MonoBehaviour
	{
		private Canvas canvas;

		private RectTransform panel;

		private TextMeshProUGUI tokenText;

		private TextMeshProUGUI promptText;

		private Image progressBg;

		private Image progressFg;

		private float tokenTimer;

		private bool isHolding;

		private float holdTime;

		private bool reviveAvailable;

		private string reviveTargetNick = "";

		private void Start()
		{
			BuildUI();
		}

		private void BuildUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00d4: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: U