Decompiled source of PeakScoreboard v1.0.0

plugins/PeakScoreboard.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PeakScoreboard.Api;
using PeakScoreboard.UI;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;
using Zorro.ControllerSupport;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Arman Ossi Loko")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 Arman Ossi Loko and Fake Game Developers")]
[assembly: AssemblyDescription("Toggle PEAK scoreboard with alive/dead status, host-only respawn, and a public API for other mods to add columns and actions.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+da3161ecd2c433122af6cb2607bc483f6439456f")]
[assembly: AssemblyProduct("PeakScoreboard")]
[assembly: AssemblyTitle("PeakScoreboard")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
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;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	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")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace PeakScoreboard
{
	internal static class AfflictionIconResolver
	{
		private static readonly Dictionary<STATUSTYPE, Sprite> Sprites = new Dictionary<STATUSTYPE, Sprite>();

		private static readonly Dictionary<STATUSTYPE, Color> Colors = new Dictionary<STATUSTYPE, Color>();

		private static float _nextRetryAt;

		public static void EnsureCache()
		{
			if (Sprites.Count < 8 && !(Time.unscaledTime < _nextRetryAt))
			{
				_nextRetryAt = Time.unscaledTime + 1f;
				TryCacheFromStatusSprites();
				TryCacheFromStaminaBar();
			}
		}

		public static bool TryGet(STATUSTYPE type, out Sprite? sprite, out Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			EnsureCache();
			color = GetColor(type);
			if (Sprites.TryGetValue(type, out sprite) && (Object)(object)sprite != (Object)null)
			{
				return true;
			}
			sprite = null;
			return false;
		}

		public static Color GetColor(STATUSTYPE type)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			EnsureCache();
			if (!Colors.TryGetValue(type, out var value))
			{
				return FallbackColor(type);
			}
			return value;
		}

		public unsafe static string DisplayName(STATUSTYPE type)
		{
			return ((object)(*(STATUSTYPE*)(&type))/*cast due to .constrained prefix*/).ToString();
		}

		private static void TryCacheFromStatusSprites()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			Sprite[] all;
			try
			{
				all = Resources.FindObjectsOfTypeAll<Sprite>();
			}
			catch
			{
				return;
			}
			foreach (STATUSTYPE value in Enum.GetValues(typeof(STATUSTYPE)))
			{
				if (!Sprites.ContainsKey(value))
				{
					Sprite val2 = FindStatusSprite(all, value);
					if ((Object)(object)val2 != (Object)null)
					{
						Sprites[value] = val2;
					}
				}
			}
		}

		private unsafe static Sprite? FindStatusSprite(Sprite[] all, STATUSTYPE type)
		{
			string text = ((object)(*(STATUSTYPE*)(&type))/*cast due to .constrained prefix*/).ToString();
			string[] array = new string[4]
			{
				"Status_" + text,
				"Status " + text,
				"Status" + text,
				text + "_Status"
			};
			string[] array2 = array;
			foreach (string value in array2)
			{
				foreach (Sprite val in all)
				{
					if ((Object)(object)val != (Object)null && ((Object)val).name.Equals(value, StringComparison.OrdinalIgnoreCase))
					{
						return val;
					}
				}
			}
			foreach (Sprite val2 in all)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					string name = ((Object)val2).name;
					if (name.IndexOf("Status", StringComparison.OrdinalIgnoreCase) >= 0 && name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return val2;
					}
				}
			}
			return null;
		}

		private static void TryCacheFromStaminaBar()
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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)
			GUIManager instance = GUIManager.instance;
			StaminaBar val = (((Object)(object)instance != (Object)null) ? instance.bar : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (val.afflictions != null)
			{
				BarAffliction[] afflictions = val.afflictions;
				foreach (BarAffliction val2 in afflictions)
				{
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.icon == (Object)null))
					{
						Colors[val2.afflictionType] = ((Graphic)val2.icon).color;
						if (!Sprites.ContainsKey(val2.afflictionType) && (Object)(object)val2.icon.sprite != (Object)null)
						{
							Sprites[val2.afflictionType] = val2.icon.sprite;
						}
					}
				}
			}
			if ((Object)(object)val.petrifyAffliction != (Object)null && (Object)(object)val.petrifyAffliction.icon != (Object)null)
			{
				Colors[(STATUSTYPE)13] = ((Graphic)val.petrifyAffliction.icon).color;
				if (!Sprites.ContainsKey((STATUSTYPE)13) && (Object)(object)val.petrifyAffliction.icon.sprite != (Object)null)
				{
					Sprites[(STATUSTYPE)13] = val.petrifyAffliction.icon.sprite;
				}
			}
		}

		private static Color FallbackColor(STATUSTYPE type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected I4, 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)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			return (Color)((int)type switch
			{
				0 => new Color(0.92f, 0.35f, 0.32f, 1f), 
				1 => new Color(0.92f, 0.62f, 0.28f, 1f), 
				2 => new Color(0.45f, 0.75f, 0.95f, 1f), 
				3 => new Color(0.55f, 0.85f, 0.35f, 1f), 
				8 => new Color(0.95f, 0.45f, 0.2f, 1f), 
				6 => new Color(0.65f, 0.55f, 0.85f, 1f), 
				5 => new Color(0.55f, 0.3f, 0.7f, 1f), 
				9 => new Color(0.7f, 0.8f, 0.35f, 1f), 
				10 => new Color(0.75f, 0.55f, 0.9f, 1f), 
				7 => new Color(0.55f, 0.4f, 0.28f, 1f), 
				11 => new Color(0.85f, 0.85f, 0.8f, 1f), 
				12 => new Color(0.9f, 0.75f, 0.4f, 1f), 
				13 => new Color(0.55f, 0.55f, 0.6f, 1f), 
				4 => new Color(0.9f, 0.4f, 0.35f, 1f), 
				14 => new Color(0.4f, 0.75f, 0.4f, 1f), 
				_ => Color.white, 
			});
		}
	}
	internal sealed class ModConfig
	{
		public ConfigEntry<string> KeyboardHoldPath { get; }

		public ConfigEntry<string> ControllerHoldPath { get; }

		public ConfigEntry<bool> ApplyRevivePenalty { get; }

		public ConfigEntry<bool> RespawnBesideLocal { get; }

		public ConfigEntry<float> RespawnVerticalOffset { get; }

		public ModConfig(ConfigFile config)
		{
			KeyboardHoldPath = config.Bind<string>("Controls", "KeyboardHoldPath", "<Keyboard>/z", "Default / config keyboard path for the scoreboard toggle. Examples: <Keyboard>/z, <Keyboard>/tab, <Keyboard>/capsLock, <Mouse>/forwardButton. Leave empty to disable the keyboard binding. In-game rebinds (Pause → CONTROLS → Scoreboard) take priority and sync back here.");
			ControllerHoldPath = config.Bind<string>("Controls", "ControllerHoldPath", "<Gamepad>/select", "Default / config gamepad path for the scoreboard toggle. Examples: <Gamepad>/select, <Gamepad>/start, <Gamepad>/leftShoulder. Leave empty to disable the controller binding. In-game rebinds (Pause → CONTROLS → Scoreboard) take priority and sync back here.");
			ApplyRevivePenalty = config.Bind<bool>("Respawn", "ApplyRevivePenalty", true, "If true, revived scouts receive the vanilla revive curse and hunger. If false, they come back clean.");
			RespawnBesideLocal = config.Bind<bool>("Respawn", "RespawnBesideLocal", true, "If true, dead scouts respawn next to you (when you are alive). Otherwise they revive at their current position.");
			RespawnVerticalOffset = config.Bind<float>("Respawn", "RespawnVerticalOffset", 2f, "Meters above the revive anchor used when warping a revived scout (helps avoid physics flings).");
		}
	}
	internal readonly struct ScoutAvatar
	{
		public Color SkinColor { get; }

		public Texture? SteamAvatar { get; }

		public Texture? Eyes { get; }

		public Texture? Mouth { get; }

		public Texture? Accessory { get; }

		public bool HasSteamAvatar => (Object)(object)SteamAvatar != (Object)null;

		public static ScoutAvatar Fallback { get; } = new ScoutAvatar(new Color(0.55f, 0.58f, 0.56f, 1f), null, null, null, null);

		public ScoutAvatar(Color skinColor, Texture? steamAvatar, Texture? eyes, Texture? mouth, Texture? accessory)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SkinColor = skinColor;
			SteamAvatar = steamAvatar;
			Eyes = eyes;
			Mouth = mouth;
			Accessory = accessory;
		}
	}
	internal static class PlayerAvatarResolver
	{
		private static readonly Dictionary<ulong, Texture2D> SteamAvatarCache = new Dictionary<ulong, Texture2D>();

		private static readonly HashSet<ulong> SteamAvatarRequested = new HashSet<ulong>();

		public static ScoutAvatar Resolve(Character character)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)character == (Object)null)
				{
					return ScoutAvatar.Fallback;
				}
				Color skinColor = ScoutAvatar.Fallback.SkinColor;
				if ((Object)(object)character.refs?.customization != (Object)null)
				{
					skinColor = character.refs.customization.PlayerColor;
				}
				Texture steamAvatar = TryGetSteamAvatar(character);
				CharacterCustomizationData val = TryGetCustomizationData(character);
				Customization instance = Singleton<Customization>.Instance;
				Texture eyes = null;
				Texture mouth = null;
				Texture accessory = null;
				if (val != null && (Object)(object)instance != (Object)null)
				{
					eyes = SafeTexture(instance.eyes, val.currentEyes);
					mouth = SafeTexture(instance.mouths, val.currentMouth);
					accessory = SafeAccessory(instance.accessories, val.currentAccessory);
				}
				return new ScoutAvatar(skinColor, steamAvatar, eyes, mouth, accessory);
			}
			catch
			{
				return ScoutAvatar.Fallback;
			}
		}

		private static Texture? TryGetSteamAvatar(Character character)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			if (!SteamManager.Initialized)
			{
				return null;
			}
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)character).photonView;
				Player val = ((photonView != null) ? photonView.Owner : null);
				if (val == null || string.IsNullOrEmpty(val.UserId))
				{
					return null;
				}
				if (!ulong.TryParse(val.UserId, out var result) || result == 0L)
				{
					return null;
				}
				if (SteamAvatarCache.TryGetValue(result, out Texture2D value) && (Object)(object)value != (Object)null)
				{
					return (Texture?)(object)value;
				}
				CSteamID val2 = default(CSteamID);
				((CSteamID)(ref val2))..ctor(result);
				int largeFriendAvatar = SteamFriends.GetLargeFriendAvatar(val2);
				switch (largeFriendAvatar)
				{
				case -1:
					if (SteamAvatarRequested.Add(result))
					{
						SteamFriends.RequestUserInformation(val2, false);
					}
					return null;
				case 0:
					return null;
				default:
				{
					uint num = default(uint);
					uint num2 = default(uint);
					if (!SteamUtils.GetImageSize(largeFriendAvatar, ref num, ref num2) || num == 0 || num2 == 0)
					{
						return null;
					}
					byte[] array = new byte[num * num2 * 4];
					if (!SteamUtils.GetImageRGBA(largeFriendAvatar, array, array.Length))
					{
						return null;
					}
					FlipVertically(array, (int)num, (int)num2);
					Texture2D val3 = new Texture2D((int)num, (int)num2, (TextureFormat)4, false);
					((Object)val3).name = $"PeakScoreboard_SteamAvatar_{result}";
					val3.LoadRawTextureData(array);
					val3.Apply(false, true);
					SteamAvatarCache[result] = val3;
					return (Texture?)(object)val3;
				}
				}
			}
			catch
			{
				return null;
			}
		}

		private static void FlipVertically(byte[] rgba, int width, int height)
		{
			int num = width * 4;
			byte[] array = new byte[num];
			for (int i = 0; i < height / 2; i++)
			{
				int num2 = i * num;
				int num3 = (height - 1 - i) * num;
				Buffer.BlockCopy(rgba, num2, array, 0, num);
				Buffer.BlockCopy(rgba, num3, rgba, num2, num);
				Buffer.BlockCopy(array, 0, rgba, num3, num);
			}
		}

		private static CharacterCustomizationData? TryGetCustomizationData(Character character)
		{
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)character).photonView;
				Player val = ((photonView != null) ? photonView.Owner : null);
				if (val == null)
				{
					return null;
				}
				PersistentPlayerDataService service = GameHandler.GetService<PersistentPlayerDataService>();
				return ((service != null) ? service.GetPlayerData(val) : null)?.customizationData;
			}
			catch
			{
				return null;
			}
		}

		private static Texture? SafeTexture(CustomizationOption[]? options, int index)
		{
			if (options == null || index < 0 || index >= options.Length)
			{
				return null;
			}
			CustomizationOption val = options[index];
			if ((Object)(object)val == (Object)null || val.isBlank || (Object)(object)val.texture == (Object)null)
			{
				return null;
			}
			return val.texture;
		}

		private static Texture? SafeAccessory(CustomizationOption[]? options, int index)
		{
			if (options == null || index < 0 || index >= options.Length)
			{
				return null;
			}
			CustomizationOption val = options[index];
			if ((Object)(object)val == (Object)null || val.isBlank || val.isThirdEye || (Object)(object)val.texture == (Object)null)
			{
				return null;
			}
			return val.texture;
		}
	}
	internal readonly struct PlayerRunStats
	{
		public float HeightMeters { get; }

		public float MaxHeightMeters { get; }

		public float DistanceMeters { get; }

		public int Deaths { get; }

		public PlayerRunStats(float heightMeters, float maxHeightMeters, float distanceMeters, int deaths)
		{
			HeightMeters = heightMeters;
			MaxHeightMeters = maxHeightMeters;
			DistanceMeters = distanceMeters;
			Deaths = deaths;
		}
	}
	internal static class PlayerStatsTracker
	{
		private sealed class TrackedScout
		{
			private Vector3? _lastPosition;

			private bool _wasDead;

			private bool _initialized;

			public int ActorId { get; }

			public float DistanceMeters { get; private set; }

			public float MaxHeightMeters { get; private set; }

			public int Deaths { get; private set; }

			public TrackedScout(int actorId)
			{
				ActorId = actorId;
			}

			public void Update(Character character)
			{
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				bool flag = (Object)(object)character.data != (Object)null && (character.data.dead || character.IsGhost);
				if (_initialized && !_wasDead && flag)
				{
					Deaths++;
				}
				_wasDead = flag;
				_initialized = true;
				CharacterStats val = ((character.refs != null) ? character.refs.stats : null);
				if ((Object)(object)val != (Object)null)
				{
					MaxHeightMeters = Mathf.Max(MaxHeightMeters, val.heightInMeters);
				}
				if (flag || character.warping)
				{
					_lastPosition = null;
					return;
				}
				Vector3 center = character.Center;
				if (!_lastPosition.HasValue)
				{
					_lastPosition = center;
					return;
				}
				Vector3 val2 = center - _lastPosition.Value;
				val2.y = 0f;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				_lastPosition = center;
				if (!(magnitude < 0.02f) && !(magnitude > 12f))
				{
					DistanceMeters += magnitude * CharacterStats.unitsToMeters;
				}
			}
		}

		private const float MinStepUnits = 0.02f;

		private const float MaxStepUnits = 12f;

		private static readonly Dictionary<int, TrackedScout> ByActor = new Dictionary<int, TrackedScout>();

		private static Guid _runId = Guid.Empty;

		public static void Tick()
		{
			EnsureRun();
			foreach (Character item in EnumeratePlayerCharacters())
			{
				int actorId = GetActorId(item);
				if (actorId > 0)
				{
					if (!ByActor.TryGetValue(actorId, out TrackedScout value))
					{
						value = new TrackedScout(actorId);
						ByActor[actorId] = value;
					}
					value.Update(item);
				}
			}
		}

		public static PlayerRunStats GetStats(Character character, int actorId)
		{
			EnsureRun();
			float num = 0f;
			int num2 = 0;
			CharacterStats val = ((character.refs != null) ? character.refs.stats : null);
			if ((Object)(object)val != (Object)null)
			{
				num = val.heightInMeters;
				num2 = CountTimelineDeaths(val);
			}
			if (actorId > 0 && ByActor.TryGetValue(actorId, out TrackedScout value))
			{
				return new PlayerRunStats(num, Mathf.Max(value.MaxHeightMeters, num), value.DistanceMeters, Math.Max(value.Deaths, num2));
			}
			return new PlayerRunStats(num, num, 0f, num2);
		}

		private static IEnumerable<Character> EnumeratePlayerCharacters()
		{
			if (PlayerHandler.Exists)
			{
				List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
				if (allPlayerCharacters != null && allPlayerCharacters.Count > 0)
				{
					foreach (Character item in allPlayerCharacters)
					{
						if ((Object)(object)item != (Object)null && !item.isBot && !item.isZombie)
						{
							yield return item;
						}
					}
					yield break;
				}
			}
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if ((Object)(object)allCharacter != (Object)null && !allCharacter.isBot && !allCharacter.isZombie)
				{
					yield return allCharacter;
				}
			}
		}

		private static int GetActorId(Character character)
		{
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)character).photonView;
				return (photonView != null) ? photonView.OwnerActorNr : (-1);
			}
			catch
			{
				return -1;
			}
		}

		private static void EnsureRun()
		{
			Guid guid = Guid.Empty;
			try
			{
				if ((Object)(object)RunManager.Instance != (Object)null)
				{
					guid = RunManager.Instance.RunId;
				}
			}
			catch
			{
			}
			if (!(guid == Guid.Empty) && _runId != guid)
			{
				_runId = guid;
				ByActor.Clear();
			}
		}

		private static int CountTimelineDeaths(CharacterStats stats)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (stats.timelineInfo == null || stats.timelineInfo.Count == 0)
			{
				return 0;
			}
			int num = 0;
			foreach (TimelineInfo item in stats.timelineInfo)
			{
				TimelineInfo current = item;
				if (((TimelineInfo)(ref current)).died)
				{
					num++;
				}
			}
			return num;
		}
	}
	internal readonly struct PlayerStatusRow
	{
		public Character Character { get; }

		public int ActorId { get; }

		public string Name { get; }

		public bool IsLocal { get; }

		public bool IsDead { get; }

		public bool IsPassedOut { get; }

		public PlayerRunStats Stats { get; }

		public PlayerVitals Vitals { get; }

		public string StatusLabel
		{
			get
			{
				if (IsDead)
				{
					return "Dead";
				}
				if (IsPassedOut)
				{
					return "Down";
				}
				return "Alive";
			}
		}

		public bool CanRespawn
		{
			get
			{
				if (!IsDead)
				{
					return Character.IsGhost;
				}
				return true;
			}
		}

		public int StatusRank
		{
			get
			{
				if (!IsDead)
				{
					return IsPassedOut ? 1 : 0;
				}
				return 2;
			}
		}

		public PlayerStatusRow(Character character, int actorId, string name, bool isLocal, bool isDead, bool isPassedOut, PlayerRunStats stats, PlayerVitals vitals)
		{
			Character = character;
			ActorId = actorId;
			Name = name;
			IsLocal = isLocal;
			IsDead = isDead;
			IsPassedOut = isPassedOut;
			Stats = stats;
			Vitals = vitals;
		}
	}
	internal static class PlayerStatusService
	{
		public static IReadOnlyList<PlayerStatusRow> Capture()
		{
			Character[] playerCharacters = GetPlayerCharacters();
			List<PlayerStatusRow> list = new List<PlayerStatusRow>(playerCharacters.Length);
			Character[] array = playerCharacters;
			foreach (Character val in array)
			{
				int actorId = GetActorId(val);
				string name = ResolveName(val);
				bool flag = (Object)(object)val.data != (Object)null && (val.data.dead || val.IsGhost);
				bool isPassedOut = !flag && (Object)(object)val.data != (Object)null && (val.data.passedOut || val.data.fullyPassedOut);
				PlayerRunStats stats = PlayerStatsTracker.GetStats(val, actorId);
				PlayerVitals vitals = PlayerVitals.Capture(val);
				list.Add(new PlayerStatusRow(val, actorId, name, (Object)(object)val == (Object)(object)Character.localCharacter, flag, isPassedOut, stats, vitals));
			}
			return (from row in list
				orderby row.StatusRank, row.Stats.MaxHeightMeters descending, row.Stats.HeightMeters descending, row.Stats.DistanceMeters descending, row.Stats.Deaths
				select row).ThenBy<PlayerStatusRow, string>((PlayerStatusRow row) => row.Name, StringComparer.OrdinalIgnoreCase).ThenBy((PlayerStatusRow row) => row.ActorId).ToArray();
		}

		private static Character[] GetPlayerCharacters()
		{
			if (!PlayerHandler.Exists)
			{
				return Filter(Character.AllCharacters);
			}
			List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters();
			if (allPlayerCharacters != null && allPlayerCharacters.Count > 0)
			{
				return Filter(allPlayerCharacters);
			}
			return Filter(Character.AllCharacters);
		}

		private static Character[] Filter(IEnumerable<Character>? source)
		{
			if (source == null)
			{
				return Array.Empty<Character>();
			}
			return source.Where((Character character) => (Object)(object)character != (Object)null && !character.isBot && !character.isZombie).ToArray();
		}

		private static string ResolveName(Character character)
		{
			if (!string.IsNullOrWhiteSpace(character.characterName))
			{
				return character.characterName;
			}
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)character).photonView;
				object obj;
				if (photonView == null)
				{
					obj = null;
				}
				else
				{
					Player owner = photonView.Owner;
					obj = ((owner != null) ? owner.NickName : null);
				}
				string text = (string)obj;
				if (!string.IsNullOrWhiteSpace(text))
				{
					return text;
				}
			}
			catch
			{
			}
			if (!((Object)(object)((Component)character).gameObject != (Object)null))
			{
				return "Scout";
			}
			return ((Object)((Component)character).gameObject).name;
		}

		private static int GetActorId(Character character)
		{
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)character).photonView;
				return (photonView != null) ? photonView.OwnerActorNr : (-1);
			}
			catch
			{
				return -1;
			}
		}
	}
	internal readonly struct PlayerEffect
	{
		public STATUSTYPE Type { get; }

		public float Amount { get; }

		public int Points => Mathf.RoundToInt(Amount * 100f);

		public PlayerEffect(STATUSTYPE type, float amount)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			Type = type;
			Amount = amount;
		}
	}
	internal readonly struct PlayerVitals
	{
		private static readonly STATUSTYPE[] TrackedStatuses;

		public bool IsHost { get; }

		public float Stamina { get; }

		public float ExtraStamina { get; }

		public float MaxStamina { get; }

		public float AvailableStamina { get; }

		public IReadOnlyList<PlayerEffect> Effects { get; }

		public float ExtraStaminaFraction => Mathf.Clamp01(ExtraStamina);

		public int AvailablePoints => Mathf.RoundToInt(Mathf.Clamp01(AvailableStamina) * 100f);

		public PlayerVitals(bool isHost, float stamina, float extraStamina, float maxStamina, float availableStamina, IReadOnlyList<PlayerEffect> effects)
		{
			IsHost = isHost;
			Stamina = stamina;
			ExtraStamina = extraStamina;
			MaxStamina = maxStamina;
			AvailableStamina = availableStamina;
			Effects = effects;
		}

		public static PlayerVitals Capture(Character character)
		{
			bool flag = false;
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)character).photonView;
				Player val = ((photonView != null) ? photonView.Owner : null);
				flag = val != null && val.IsMasterClient;
				if (!flag && (Object)(object)character == (Object)(object)Character.localCharacter && PhotonNetwork.IsMasterClient)
				{
					flag = true;
				}
			}
			catch
			{
			}
			float num = 0f;
			float extraStamina = 0f;
			float maxStamina = 1f;
			float availableStamina = 0f;
			if ((Object)(object)character.data != (Object)null)
			{
				num = Mathf.Clamp01(character.data.currentStamina);
				extraStamina = Mathf.Clamp01(character.data.extraStamina);
				try
				{
					maxStamina = Mathf.Max(0f, character.GetMaxStamina());
				}
				catch
				{
					maxStamina = 1f;
				}
				availableStamina = num;
			}
			return new PlayerVitals(flag, num, extraStamina, maxStamina, availableStamina, CaptureEffects(character));
		}

		private static IReadOnlyList<PlayerEffect> CaptureEffects(Character character)
		{
			//IL_003a: 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_0040: Invalid comparison between Unknown and I4
			//IL_006c: 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)
			CharacterAfflictions val = ((character.refs != null) ? character.refs.afflictions : null);
			if ((Object)(object)val == (Object)null)
			{
				return Array.Empty<PlayerEffect>();
			}
			List<PlayerEffect> list = new List<PlayerEffect>(6);
			STATUSTYPE[] trackedStatuses = TrackedStatuses;
			foreach (STATUSTYPE val2 in trackedStatuses)
			{
				try
				{
					float num = (((int)val2 != 13 || !((Object)(object)character.data != (Object)null)) ? val.GetCurrentStatus(val2) : Mathf.Clamp01((float)character.data.petrifyAmount / 100f));
					if (num >= 0.0095f)
					{
						list.Add(new PlayerEffect(val2, num));
					}
				}
				catch
				{
				}
			}
			return list;
		}

		static PlayerVitals()
		{
			STATUSTYPE[] array = new STATUSTYPE[15];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			TrackedStatuses = (STATUSTYPE[])(object)array;
		}
	}
	[BepInPlugin("PeakScoreboard", "PeakScoreboard", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony? _harmony;

		private ModConfig _config;

		private ScoreboardController? _controller;

		public const string Id = "PeakScoreboard";

		internal static Plugin? Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "PeakScoreboard";

		public static string Version => "1.0.0";

		private void Awake()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_config = new ModConfig(((BaseUnityPlugin)this).Config);
			ScoreboardAction.Initialize(Log, _config);
			_controller = new ScoreboardController(_config, Log);
			_harmony = new Harmony("PeakScoreboard");
			try
			{
				_harmony.PatchAll(typeof(GuiManagerAttachPatch));
				_harmony.PatchAll(typeof(CharacterInputInitPatch));
				RebindControlsPatch.Install(_harmony, Log);
				Log.LogInfo((object)(Name + " v" + Version + " loaded. Press Scoreboard (default Z) to toggle the player list."));
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to patch: {arg}");
			}
		}

		private void Update()
		{
			PlayerStatsTracker.Tick();
			_controller?.Tick();
		}

		internal void AttachUi()
		{
			_controller?.Attach();
		}

		private void OnDestroy()
		{
			_controller?.Dispose();
			_controller = null;
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}
	}
	[HarmonyPatch(typeof(GUIManager), "Start")]
	internal static class GuiManagerAttachPatch
	{
		private static void Postfix()
		{
			Plugin.Instance?.AttachUi();
		}
	}
	[HarmonyPatch(typeof(CharacterInput), "Init")]
	internal static class CharacterInputInitPatch
	{
		private static void Prefix()
		{
			ScoreboardAction.EnsureRegistered();
		}

		private static void Postfix()
		{
			ScoreboardAction.OnGameBindingsLoaded();
		}
	}
	internal static class RebindControlsPatch
	{
		private const string InjectedObjectName = "PeakScoreboard_RebindButton";

		private const string InjectedKeyboardName = "PeakScoreboard_RebindButton_KB";

		private const string InjectedGamepadName = "PeakScoreboard_RebindButton_GP";

		private static ManualLogSource? _logger;

		private static bool _patched;

		public static void Install(Harmony harmony, ManualLogSource logger)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			_logger = logger;
			if (!_patched)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(PauseMenuControlsPage), "InitButtons", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					logger.LogWarning((object)"PauseMenuControlsPage.InitButtons not found; Scoreboard will not appear in Rebind controls.");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(RebindControlsPatch), "InitButtonsPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_patched = true;
			}
		}

		private static void InitButtonsPrefix(PauseMenuControlsPage __instance)
		{
			try
			{
				ScoreboardAction.EnsureRegistered();
				EnsureButtons(__instance);
			}
			catch (Exception arg)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogWarning((object)$"Failed to inject Scoreboard rebind control: {arg}");
				}
			}
		}

		private static void EnsureButtons(PauseMenuControlsPage page)
		{
			Transform controlsMenuButtonsParent = page.controlsMenuButtonsParent;
			if ((Object)(object)controlsMenuButtonsParent == (Object)null)
			{
				return;
			}
			PauseMenuRebindButton[] componentsInChildren = ((Component)controlsMenuButtonsParent).GetComponentsInChildren<PauseMenuRebindButton>(true);
			if (componentsInChildren.Length == 0)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogWarning((object)"No PauseMenuRebindButton template found to clone for Scoreboard.");
				}
				return;
			}
			PauseMenuRebindButton val = FindTemplate(componentsInChildren, preferKeyboard: true);
			PauseMenuRebindButton val2 = FindTemplate(componentsInChildren, preferKeyboard: false);
			DestroyLegacyMisplacedClone(controlsMenuButtonsParent, (val != null) ? ((Component)val).transform.parent : null, (val2 != null) ? ((Component)val2).transform.parent : null);
			bool flag = false;
			if ((Object)(object)val != (Object)null)
			{
				flag |= EnsureClone(val, "PeakScoreboard_RebindButton_KB");
			}
			if ((Object)(object)val2 != (Object)null && (Object)(object)val != (Object)null && (Object)(object)((Component)val2).transform.parent != (Object)(object)((Component)val).transform.parent)
			{
				flag |= EnsureClone(val2, "PeakScoreboard_RebindButton_GP");
			}
			else if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null)
			{
				flag |= EnsureClone(val2, "PeakScoreboard_RebindButton_GP");
			}
			if (flag)
			{
				AccessTools.Field(typeof(PauseMenuControlsPage), "initializedButtons")?.SetValue(page, false);
				RectTransform val3 = (RectTransform)(object)((controlsMenuButtonsParent is RectTransform) ? controlsMenuButtonsParent : null);
				if ((Object)(object)val3 != (Object)null)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(val3);
				}
				ManualLogSource? logger2 = _logger;
				if (logger2 != null)
				{
					logger2.LogInfo((object)"Added Scoreboard to Rebind controls.");
				}
			}
		}

		private static void DestroyLegacyMisplacedClone(Transform root, Transform? keyboardParent, Transform? gamepadParent)
		{
			PauseMenuRebindButton[] componentsInChildren = ((Component)root).GetComponentsInChildren<PauseMenuRebindButton>(true);
			PauseMenuRebindButton[] array = componentsInChildren;
			foreach (PauseMenuRebindButton val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name = ((Object)((Component)val).gameObject).name;
				if (name == "PeakScoreboard_RebindButton" || name.StartsWith("PeakScoreboard_RebindButton", StringComparison.Ordinal))
				{
					Transform parent = ((Component)val).transform.parent;
					if (!((Object)(object)parent != (Object)null) || (!((Object)(object)parent == (Object)(object)keyboardParent) && !((Object)(object)parent == (Object)(object)gamepadParent)) || (!(name == "PeakScoreboard_RebindButton_KB") && !(name == "PeakScoreboard_RebindButton_GP")))
					{
						Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
					}
				}
			}
		}

		private static PauseMenuRebindButton? FindTemplate(PauseMenuRebindButton[] templates, bool preferKeyboard)
		{
			PauseMenuRebindButton val = null;
			foreach (PauseMenuRebindButton val2 in templates)
			{
				if (!((Object)(object)val2 == (Object)null) && !string.Equals(val2.inputActionName, "Pause", StringComparison.OrdinalIgnoreCase) && !((Object)((Component)val2).gameObject).name.StartsWith("PeakScoreboard_RebindButton", StringComparison.Ordinal))
				{
					if (val == null)
					{
						val = val2;
					}
					string name = ((Object)((Component)val2).gameObject).name;
					bool flag = name.IndexOf("KB", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Keyboard", StringComparison.OrdinalIgnoreCase) >= 0;
					bool flag2 = name.IndexOf("GP", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Gamepad", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Controller", StringComparison.OrdinalIgnoreCase) >= 0;
					if (preferKeyboard && flag)
					{
						return val2;
					}
					if (!preferKeyboard && flag2)
					{
						return val2;
					}
				}
			}
			foreach (PauseMenuRebindButton val3 in templates)
			{
				if (!((Object)(object)val3 == (Object)null) && !string.Equals(val3.inputActionName, "Pause", StringComparison.OrdinalIgnoreCase) && !((Object)((Component)val3).gameObject).name.StartsWith("PeakScoreboard_RebindButton", StringComparison.Ordinal) && ((Component)val3).gameObject.activeInHierarchy)
				{
					return val3;
				}
			}
			return val;
		}

		private static bool EnsureClone(PauseMenuRebindButton template, string objectName)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Component)template).transform.parent;
			if ((Object)(object)parent == (Object)null)
			{
				return false;
			}
			Transform val = parent.Find(objectName);
			if ((Object)(object)val != (Object)null)
			{
				return false;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, parent);
			((Object)val2).name = objectName;
			val2.SetActive(((Component)template).gameObject.activeSelf);
			val2.transform.SetAsLastSibling();
			Transform transform = val2.transform;
			RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = ((Component)template).transform;
			RectTransform val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
			{
				((Transform)val3).localScale = ((Transform)val4).localScale;
				val3.anchorMin = val4.anchorMin;
				val3.anchorMax = val4.anchorMax;
				val3.pivot = val4.pivot;
				val3.sizeDelta = val4.sizeDelta;
				val3.anchoredPosition = val4.anchoredPosition;
			}
			PauseMenuRebindButton component = val2.GetComponent<PauseMenuRebindButton>();
			component.inputActionName = "Scoreboard";
			AccessTools.Field(typeof(PauseMenuRebindButton), "inputAction")?.SetValue(component, ScoreboardAction.Action);
			if ((Object)(object)component.inputDescriptionText != (Object)null)
			{
				component.inputDescriptionText.index = "SCOREBOARD";
				component.inputDescriptionText.autoSet = false;
				if ((Object)(object)component.inputDescriptionText.tmp != (Object)null)
				{
					component.inputDescriptionText.tmp.text = "Scoreboard";
				}
			}
			else
			{
				TextMeshProUGUI componentInChildren = val2.GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = "Scoreboard";
				}
			}
			ReplaceBindingGlyphs(val2);
			LayoutGroup component2 = ((Component)parent).GetComponent<LayoutGroup>();
			if ((Object)(object)component2 != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((parent is RectTransform) ? parent : null));
			}
			return true;
		}

		private static void ReplaceBindingGlyphs(GameObject clone)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			InputIcon[] componentsInChildren = clone.GetComponentsInChildren<InputIcon>(true);
			InputIcon[] array = componentsInChildren;
			foreach (InputIcon val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					TMP_Text val2 = val.text;
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = ((Component)val).GetComponent<TMP_Text>();
					}
					Object.Destroy((Object)(object)val);
					if (!((Object)(object)val2 == (Object)null))
					{
						ScoreboardBindingGlyph scoreboardBindingGlyph = ((Component)val2).gameObject.GetComponent<ScoreboardBindingGlyph>() ?? ((Component)val2).gameObject.AddComponent<ScoreboardBindingGlyph>();
						scoreboardBindingGlyph.Bind(val2);
						scoreboardBindingGlyph.Refresh(InputHandler.GetCurrentUsedInputScheme());
					}
				}
			}
		}
	}
	internal sealed class RespawnService
	{
		private readonly ModConfig _config;

		private readonly ManualLogSource _logger;

		public RespawnService(ModConfig config, ManualLogSource logger)
		{
			_config = config;
			_logger = logger;
		}

		public bool CanRespawn(out string reason)
		{
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
			{
				reason = "Only the host can respawn players.";
				return false;
			}
			reason = string.Empty;
			return true;
		}

		public bool TryRespawn(Character target, out string message)
		{
			//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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				message = "No target.";
				return false;
			}
			if (!CanRespawn(out string reason))
			{
				message = reason;
				return false;
			}
			if (!((Object)(object)target.data != (Object)null) || (!target.data.dead && !target.IsGhost))
			{
				message = ResolveName(target) + " is not dead.";
				return false;
			}
			Vector3 val = ResolveRespawnPosition(target);
			bool value = _config.ApplyRevivePenalty.Value;
			try
			{
				if (target.IsLocal)
				{
					PhotonView val2 = ((target.refs != null && (Object)(object)target.refs.view != (Object)null) ? target.refs.view : ((MonoBehaviourPun)target).photonView);
					val2.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { val, value, -1 });
				}
				else if (target.refs != null && (Object)(object)target.refs.view != (Object)null)
				{
					target.refs.view.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { val, value, -1 });
				}
				else
				{
					if (!((Object)(object)((MonoBehaviourPun)target).photonView != (Object)null))
					{
						message = "No PhotonView for " + ResolveName(target) + ".";
						return false;
					}
					((MonoBehaviourPun)target).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { val, value, -1 });
				}
				message = "Respawning " + ResolveName(target) + "…";
				_logger.LogInfo((object)$"Requested respawn for '{ResolveName(target)}' at {val} (penalty={value}).");
				return true;
			}
			catch (Exception arg)
			{
				_logger.LogError((object)$"Failed to respawn '{ResolveName(target)}': {arg}");
				message = "Respawn failed. Check the BepInEx log.";
				return false;
			}
		}

		private Vector3 ResolveRespawnPosition(Character target)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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)
			float num = Mathf.Max(0.1f, _config.RespawnVerticalOffset.Value);
			if (_config.RespawnBesideLocal.Value)
			{
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter != (Object)(object)target && (Object)(object)localCharacter.data != (Object)null && !localCharacter.data.dead && !localCharacter.IsGhost)
				{
					return localCharacter.Center + Vector3.up * num;
				}
				Character val = FindNearestAlive(target);
				if ((Object)(object)val != (Object)null)
				{
					return val.Center + Vector3.up * num;
				}
			}
			return target.Center + Vector3.up * num;
		}

		private static Character? FindNearestAlive(Character exclude)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			Character result = null;
			float num = float.MaxValue;
			Vector3 center = exclude.Center;
			foreach (PlayerStatusRow item in PlayerStatusService.Capture())
			{
				if (!((Object)(object)item.Character == (Object)(object)exclude) && !item.IsDead)
				{
					float num2 = Vector3.Distance(center, item.Character.Center);
					if (num2 < num)
					{
						num = num2;
						result = item.Character;
					}
				}
			}
			return result;
		}

		private static string ResolveName(Character character)
		{
			if (!string.IsNullOrWhiteSpace(character.characterName))
			{
				return character.characterName;
			}
			return ((Object)character).name;
		}
	}
	internal static class ScoreboardAction
	{
		public const string ActionName = "Scoreboard";

		public const string LocalizationId = "SCOREBOARD";

		public const string DisplayLabel = "Scoreboard";

		private static ManualLogSource? _logger;

		private static ModConfig? _config;

		private static InputAction? _action;

		private static bool _registered;

		private static bool _listeningForConfigChanges;

		private static bool _gameBindingsLoaded;

		private static bool _suppressConfigApply;

		public static InputAction? Action => _action;

		public static void Initialize(ManualLogSource logger, ModConfig config)
		{
			_logger = logger;
			_config = config;
			HookConfigChanges();
			EnsureRegistered();
		}

		public static void OnGameBindingsLoaded()
		{
			_gameBindingsLoaded = true;
			EnsureRegistered();
			SyncConfigFromLiveBindings();
		}

		public static bool EnsureRegistered()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if (_registered && _action != null && _action.actionMap != null)
			{
				return true;
			}
			InputActionAsset actions = InputSystem.actions;
			if ((Object)(object)actions == (Object)null)
			{
				return false;
			}
			InputAction val = actions.FindAction("Scoreboard", false);
			if (val != null)
			{
				_action = val;
				_registered = true;
				EnsureLocalizationEntry();
				return true;
			}
			InputActionMap val2 = ((IEnumerable<InputActionMap>)(object)actions.actionMaps).FirstOrDefault((Func<InputActionMap, bool>)((InputActionMap candidate) => candidate.FindAction("Jump", false) != null)) ?? ((IEnumerable<InputActionMap>)(object)actions.actionMaps).FirstOrDefault();
			if (val2 == null)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogWarning((object)"Could not find an InputActionMap to host the Scoreboard action.");
				}
				return false;
			}
			try
			{
				bool enabled = val2.enabled;
				if (enabled)
				{
					val2.Disable();
				}
				string text = NormalizePath(_config?.KeyboardHoldPath.Value, "<Keyboard>/z");
				string text2 = NormalizePath(_config?.ControllerHoldPath.Value, "<Gamepad>/select");
				InputAction val3 = InputActionSetupExtensions.AddAction(val2, "Scoreboard", (InputActionType)1, (string)null, (string)null, (string)null, (string)null, (string)null);
				if (text.Length > 0)
				{
					InputActionSetupExtensions.AddBinding(val3, text, (string)null, (string)null, "Keyboard&Mouse");
				}
				if (text2.Length > 0)
				{
					InputActionSetupExtensions.AddBinding(val3, text2, (string)null, (string)null, "Gamepad");
				}
				if (val3.bindings.Count == 0)
				{
					InputActionSetupExtensions.AddBinding(val3, "<Keyboard>/z", (string)null, (string)null, "Keyboard&Mouse");
					ManualLogSource? logger2 = _logger;
					if (logger2 != null)
					{
						logger2.LogWarning((object)"Both scoreboard bindings were empty; fell back to <Keyboard>/z.");
					}
				}
				_action = val3;
				if (enabled)
				{
					val2.Enable();
				}
				else
				{
					val3.Enable();
				}
				EnsureLocalizationEntry();
				_registered = true;
				ManualLogSource? logger3 = _logger;
				if (logger3 != null)
				{
					logger3.LogInfo((object)("Registered InputAction 'Scoreboard' (default " + DescribeBinding(text, text2) + ")."));
				}
				return true;
			}
			catch (Exception arg)
			{
				ManualLogSource? logger4 = _logger;
				if (logger4 != null)
				{
					logger4.LogError((object)$"Failed to register Scoreboard input action: {arg}");
				}
				return false;
			}
		}

		public static bool WasPressedThisFrame()
		{
			EnsureRegistered();
			if (_action != null)
			{
				return _action.WasPressedThisFrame();
			}
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				return ((ButtonControl)current.zKey).wasPressedThisFrame;
			}
			return false;
		}

		public static void ApplyConfiguredBindings(bool save)
		{
			if (_config == null || !EnsureRegistered() || _action == null)
			{
				return;
			}
			try
			{
				string text = NormalizePath(_config.KeyboardHoldPath.Value, string.Empty);
				string text2 = NormalizePath(_config.ControllerHoldPath.Value, string.Empty);
				ApplyOrClearGroupBinding("Keyboard&Mouse", text);
				ApplyOrClearGroupBinding("Gamepad", text2);
				if (save && _gameBindingsLoaded)
				{
					Rebinding.SaveRebindingsToFile((InputActionAsset)null);
				}
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogInfo((object)("Scoreboard toggle binding set from config to " + DescribeBinding(text, text2) + "."));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logger2 = _logger;
				if (logger2 != null)
				{
					logger2.LogWarning((object)("Failed to apply scoreboard binding from config: " + ex.Message));
				}
			}
		}

		public static string GetEffectiveKeyboardPath()
		{
			EnsureRegistered();
			return GetEffectivePathForGroup("Keyboard&Mouse");
		}

		public static string GetEffectiveGamepadPath()
		{
			EnsureRegistered();
			return GetEffectivePathForGroup("Gamepad");
		}

		private static void SyncConfigFromLiveBindings()
		{
			if (_config == null || _action == null)
			{
				return;
			}
			try
			{
				string effectivePathForGroup = GetEffectivePathForGroup("Keyboard&Mouse");
				string effectivePathForGroup2 = GetEffectivePathForGroup("Gamepad");
				_suppressConfigApply = true;
				if (!string.IsNullOrEmpty(effectivePathForGroup) && _config.KeyboardHoldPath.Value != effectivePathForGroup)
				{
					_config.KeyboardHoldPath.Value = effectivePathForGroup;
				}
				if (!string.IsNullOrEmpty(effectivePathForGroup2) && _config.ControllerHoldPath.Value != effectivePathForGroup2)
				{
					_config.ControllerHoldPath.Value = effectivePathForGroup2;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogWarning((object)("Failed to sync config from live scoreboard bindings: " + ex.Message));
				}
			}
			finally
			{
				_suppressConfigApply = false;
			}
		}

		private static string GetEffectivePathForGroup(string group)
		{
			//IL_005d: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (_action == null)
			{
				return string.Empty;
			}
			for (int i = 0; i < _action.bindings.Count; i++)
			{
				InputBinding val = _action.bindings[i];
				if (!string.IsNullOrEmpty(((InputBinding)(ref val)).groups) && ((InputBinding)(ref val)).groups.Contains(group))
				{
					return ((InputBinding)(ref val)).effectivePath ?? string.Empty;
				}
			}
			return string.Empty;
		}

		private static void ApplyOrClearGroupBinding(string group, string path)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (_action == null)
			{
				return;
			}
			int num = FindBindingIndex(group);
			if (num < 0)
			{
				if (path.Length != 0)
				{
					InputActionSetupExtensions.AddBinding(_action, path, (string)null, (string)null, group);
				}
			}
			else if (path.Length == 0)
			{
				InputActionRebindingExtensions.ApplyBindingOverride(_action, num, string.Empty);
			}
			else
			{
				InputActionRebindingExtensions.ApplyBindingOverride(_action, num, path);
			}
		}

		private static int FindBindingIndex(string group)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (_action == null)
			{
				return -1;
			}
			for (int i = 0; i < _action.bindings.Count; i++)
			{
				InputBinding val = _action.bindings[i];
				if (!string.IsNullOrEmpty(((InputBinding)(ref val)).groups) && ((InputBinding)(ref val)).groups.Contains(group))
				{
					return i;
				}
			}
			return -1;
		}

		private static void HookConfigChanges()
		{
			if (!_listeningForConfigChanges && _config != null)
			{
				_config.KeyboardHoldPath.SettingChanged += OnControlPathChanged;
				_config.ControllerHoldPath.SettingChanged += OnControlPathChanged;
				_listeningForConfigChanges = true;
			}
		}

		private static void OnControlPathChanged(object sender, EventArgs e)
		{
			if (!_suppressConfigApply && _gameBindingsLoaded)
			{
				ApplyConfiguredBindings(save: true);
			}
		}

		private static string NormalizePath(string? value, string fallback)
		{
			string text = value?.Trim() ?? string.Empty;
			if (text.Length <= 0)
			{
				return fallback;
			}
			return text;
		}

		private static string DescribeBinding(string keyboardPath, string controllerPath)
		{
			string text = ((keyboardPath.Length > 0) ? keyboardPath : "(keyboard off)");
			string text2 = ((controllerPath.Length > 0) ? controllerPath : "(controller off)");
			return text + " / " + text2;
		}

		private static void EnsureLocalizationEntry()
		{
			try
			{
				Dictionary<string, List<string>> mainTable = LocalizedText.mainTable;
				if (!mainTable.ContainsKey("SCOREBOARD"))
				{
					List<string> list = new List<string>(14);
					for (int i = 0; i < 14; i++)
					{
						list.Add("Scoreboard");
					}
					mainTable["SCOREBOARD"] = list;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogWarning((object)("Could not register Scoreboard localization entry: " + ex.Message));
				}
			}
		}
	}
}
namespace PeakScoreboard.UI
{
	internal static class RuntimeUiFactory
	{
		internal static readonly Color Backdrop = new Color(0.035f, 0.043f, 0.047f, 0.55f);

		internal static readonly Color Panel = new Color(0.1f, 0.115f, 0.12f, 0.96f);

		internal static readonly Color Surface = new Color(0.16f, 0.175f, 0.18f, 1f);

		internal static readonly Color SurfaceHover = new Color(0.22f, 0.235f, 0.235f, 1f);

		internal static readonly Color Accent = new Color(0.3f, 0.78f, 0.58f, 1f);

		internal static readonly Color TextPrimary = new Color(0.95f, 0.96f, 0.94f, 1f);

		internal static readonly Color TextMuted = new Color(0.68f, 0.71f, 0.69f, 1f);

		internal static readonly Color Alive = new Color(0.45f, 0.86f, 0.58f, 1f);

		internal static readonly Color Down = new Color(0.95f, 0.78f, 0.35f, 1f);

		internal static readonly Color Dead = new Color(0.94f, 0.45f, 0.42f, 1f);

		internal static readonly Color Stamina = new Color(0.45f, 0.82f, 0.55f, 1f);

		internal static readonly Color StaminaBonus = new Color(0.95f, 0.82f, 0.3f, 1f);

		internal static readonly Color StaminaTrack = new Color(0.08f, 0.09f, 0.095f, 1f);

		internal static readonly Color HostTag = new Color(0.95f, 0.78f, 0.35f, 1f);

		private static Sprite? _whiteSprite;

		private static Sprite? _circleSprite;

		public static RectTransform CreateRect(string name, Transform parent, params Type[] components)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			Type[] array = new Type[components.Length + 1];
			array[0] = typeof(RectTransform);
			Array.Copy(components, 0, array, 1, components.Length);
			GameObject val = new GameObject(name, array);
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		public static void Stretch(RectTransform rect, float left = 0f, float right = 0f, float bottom = 0f, float top = 0f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = new Vector2(left, bottom);
			rect.offsetMax = new Vector2(0f - right, 0f - top);
		}

		public static TMP_FontAsset ResolveFont()
		{
			if ((Object)(object)FontFallbackSwapper.instance != (Object)null && (Object)(object)FontFallbackSwapper.instance.mainBaseFont != (Object)null)
			{
				return FontFallbackSwapper.instance.mainBaseFont;
			}
			TMP_FontAsset val = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset candidate) => ((Object)candidate).name == "DarumaDropOne-Regular SDF")) ?? Resources.FindObjectsOfTypeAll<TMP_FontAsset>().FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("No TextMeshPro font asset is available.");
			}
			return val;
		}

		public static TextMeshProUGUI CreateText(string name, Transform parent, TMP_FontAsset font, float fontSize, Color color, TextAlignmentOptions alignment)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = CreateRect(name, parent, typeof(TextMeshProUGUI));
			TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).font = font;
			((TMP_Text)component).fontSize = fontSize;
			((Graphic)component).color = color;
			((TMP_Text)component).alignment = alignment;
			((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component).overflowMode = (TextOverflowModes)1;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		public static Image CreateImage(string name, Transform parent, Color color, bool raycastTarget = true)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = CreateRect(name, parent, typeof(Image));
			Image component = ((Component)val).GetComponent<Image>();
			component.sprite = GetWhiteSprite();
			component.type = (Type)1;
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = raycastTarget;
			return component;
		}

		public static Button CreateButton(string name, Transform parent, TMP_FontAsset font, string label)
		{
			//IL_0042: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = CreateRect(name, parent, typeof(Image), typeof(Button));
			Image component = ((Component)val).GetComponent<Image>();
			component.sprite = GetWhiteSprite();
			component.type = (Type)1;
			((Graphic)component).color = Surface;
			Button component2 = ((Component)val).GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			((Selectable)component2).colors = CreateButtonColors();
			TextMeshProUGUI val2 = CreateText("Label", (Transform)(object)val, font, 20f, TextPrimary, (TextAlignmentOptions)514);
			((TMP_Text)val2).text = label;
			Stretch(((TMP_Text)val2).rectTransform, 4f, 4f, 2f, 2f);
			return component2;
		}

		public static ColorBlock CreateButtonColors()
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			ColorBlock defaultColorBlock = ColorBlock.defaultColorBlock;
			((ColorBlock)(ref defaultColorBlock)).normalColor = Surface;
			((ColorBlock)(ref defaultColorBlock)).highlightedColor = SurfaceHover;
			((ColorBlock)(ref defaultColorBlock)).pressedColor = Accent;
			((ColorBlock)(ref defaultColorBlock)).selectedColor = SurfaceHover;
			((ColorBlock)(ref defaultColorBlock)).disabledColor = new Color(Surface.r, Surface.g, Surface.b, 0.45f);
			((ColorBlock)(ref defaultColorBlock)).colorMultiplier = 1f;
			((ColorBlock)(ref defaultColorBlock)).fadeDuration = 0.08f;
			return defaultColorBlock;
		}

		public static Color StatusColor(PlayerStatusRow row)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (row.IsDead)
			{
				return Dead;
			}
			if (row.IsPassedOut)
			{
				return Down;
			}
			return Alive;
		}

		public static Sprite GetWhiteSprite()
		{
			//IL_0032: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_whiteSprite != (Object)null)
			{
				return _whiteSprite;
			}
			Texture2D whiteTexture = Texture2D.whiteTexture;
			_whiteSprite = Sprite.Create(whiteTexture, new Rect(0f, 0f, (float)((Texture)whiteTexture).width, (float)((Texture)whiteTexture).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(1f, 1f, 1f, 1f));
			return _whiteSprite;
		}

		public static Sprite GetCircleSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_circleSprite != (Object)null)
			{
				return _circleSprite;
			}
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			float num = 31.5f;
			float num2 = num;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num3 = (float)j - num2;
					float num4 = (float)i - num2;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					float num6 = Mathf.Clamp01(num - num5 + 0.5f);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num6));
				}
			}
			val.Apply(false, true);
			_circleSprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
			return _circleSprite;
		}

		public static RawImage CreateRawImage(string name, Transform parent)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = CreateRect(name, parent, typeof(RawImage));
			RawImage component = ((Component)val).GetComponent<RawImage>();
			((Graphic)component).raycastTarget = false;
			((Graphic)component).color = Color.white;
			return component;
		}
	}
	internal sealed class ScoreboardBindingGlyph : MonoBehaviour
	{
		private TMP_Text? _text;

		private bool _subscribed;

		public void Bind(TMP_Text text)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			_text = text;
			Refresh(InputHandler.GetCurrentUsedInputScheme());
		}

		private void OnEnable()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Subscribe();
			Refresh(InputHandler.GetCurrentUsedInputScheme());
		}

		private void OnDisable()
		{
			Unsubscribe();
		}

		private void OnDestroy()
		{
			Unsubscribe();
		}

		private void Subscribe()
		{
			if (!_subscribed)
			{
				InputHandler instance = RetrievableResourceSingleton<InputHandler>.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					instance.InputSchemeChanged = (Action<InputScheme>)Delegate.Combine(instance.InputSchemeChanged, new Action<InputScheme>(OnDeviceChange));
					_subscribed = true;
				}
			}
		}

		private void Unsubscribe()
		{
			if (_subscribed)
			{
				InputHandler instance = RetrievableResourceSingleton<InputHandler>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.InputSchemeChanged = (Action<InputScheme>)Delegate.Remove(instance.InputSchemeChanged, new Action<InputScheme>(OnDeviceChange));
				}
				_subscribed = false;
			}
		}

		private void OnDeviceChange(InputScheme scheme)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Refresh(scheme);
		}

		public void Refresh(InputScheme scheme)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			if ((Object)(object)_text == (Object)null)
			{
				return;
			}
			try
			{
				bool flag = default(bool);
				string bindingPath = InputSpriteData.GetBindingPath("Scoreboard", scheme, ref flag);
				InputSpriteData instance = SingletonAsset<InputSpriteData>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					_text.text = FormatFallback(bindingPath);
					return;
				}
				string text = (((int)scheme == 1) ? instance.GetSpriteTagFromInputPathGamepad(bindingPath) : instance.GetSpriteTagFromInputPathKeyboard(bindingPath));
				_text.text = (string.IsNullOrEmpty(text) ? FormatFallback(bindingPath) : text);
			}
			catch (Exception)
			{
				_text.text = FormatFallback(ScoreboardAction.GetEffectiveKeyboardPath());
			}
		}

		private static string FormatFallback(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return "?";
			}
			int num = path.LastIndexOf('/');
			string text = ((num >= 0 && num < path.Length - 1) ? path.Substring(num + 1) : path);
			if (text.Length != 1)
			{
				return text;
			}
			return text.ToUpperInvariant();
		}
	}
	internal sealed class ScoreboardController : IDisposable
	{
		private readonly ModConfig _config;

		private readonly ManualLogSource _logger;

		private readonly RespawnService _respawn;

		private ScoreboardView? _view;

		private bool _visible;

		private float _nextRefreshAt;

		private string _statusMessage = string.Empty;

		private bool _statusIsError;

		public ScoreboardController(ModConfig config, ManualLogSource logger)
		{
			_config = config;
			_logger = logger;
			_respawn = new RespawnService(config, logger);
		}

		public void Attach()
		{
			if (_view != null && (Object)(object)_view.Root != (Object)null)
			{
				return;
			}
			try
			{
				_view = null;
				ScoreboardAction.EnsureRegistered();
				_view = ScoreboardView.Create();
				_view.OnCloseRequested = delegate
				{
					SetVisible(visible: false);
				};
				_logger.LogInfo((object)"Scoreboard UI ready. Press Scoreboard (default Z) to toggle.");
			}
			catch (Exception arg)
			{
				_logger.LogError((object)$"Failed to create scoreboard UI: {arg}");
			}
		}

		public void Tick()
		{
			if (_view == null || (Object)(object)_view.Root == (Object)null)
			{
				if ((Object)(object)GUIManager.instance != (Object)null)
				{
					Attach();
				}
				if (_view == null || (Object)(object)_view.Root == (Object)null)
				{
					return;
				}
			}
			if (_visible && !_view.Window.IsOpen)
			{
				_visible = false;
				_view.SetChromeVisible(visible: false);
			}
			if (ScoreboardAction.WasPressedThisFrame())
			{
				if (_visible)
				{
					SetVisible(visible: false);
				}
				else if (CanShow())
				{
					SetVisible(visible: true);
				}
			}
			if (_visible)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				if (Time.unscaledTime >= _nextRefreshAt)
				{
					RefreshRows();
					_nextRefreshAt = Time.unscaledTime + 0.25f;
				}
			}
		}

		public void Dispose()
		{
			if (_visible)
			{
				_view?.Close();
			}
			_view?.Destroy();
			_view = null;
			_visible = false;
		}

		private void SetVisible(bool visible)
		{
			_visible = visible;
			if (_view != null)
			{
				if (visible)
				{
					_statusMessage = string.Empty;
					_statusIsError = false;
					_view.Open();
					RefreshRows();
					_nextRefreshAt = Time.unscaledTime + 0.25f;
				}
				else
				{
					_view.Close();
				}
			}
		}

		private void RefreshRows()
		{
			if (_view == null)
			{
				return;
			}
			IReadOnlyList<PlayerStatusRow> readOnlyList = PlayerStatusService.Capture();
			string reason;
			bool flag = _respawn.CanRespawn(out reason);
			string subtitle = (flag ? "Press Scoreboard again or Close · click Respawn on dead scouts" : reason);
			_view.SetSubtitle(subtitle);
			_view.BindRows(readOnlyList, OnRespawnClicked, flag);
			if (string.IsNullOrEmpty(_statusMessage))
			{
				int num = 0;
				int num2 = 0;
				foreach (PlayerStatusRow item in readOnlyList)
				{
					if (item.IsDead)
					{
						num2++;
					}
					else
					{
						num++;
					}
				}
				string arg = ((PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) ? " · you are host" : string.Empty);
				_view.SetStatus($"{num} alive · {num2} dead{arg}", isError: false);
			}
			else
			{
				_view.SetStatus(_statusMessage, _statusIsError);
			}
		}

		private void OnRespawnClicked(PlayerStatusRow row)
		{
			string message;
			bool flag = _respawn.TryRespawn(row.Character, out message);
			_statusMessage = message;
			_statusIsError = !flag;
			_view?.SetStatus(_statusMessage, _statusIsError);
			_nextRefreshAt = Time.unscaledTime + 0.1f;
		}

		private bool CanShow()
		{
			if (Time.timeScale <= 0f)
			{
				return false;
			}
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance != (Object)null && instance.wheelActive)
			{
				return false;
			}
			if ((Object)(object)instance != (Object)null && instance.windowBlockingInput && !_visible)
			{
				return false;
			}
			if (GUIManager.InPauseMenu)
			{
				return false;
			}
			if (!((Object)(object)Character.localCharacter != (Object)null))
			{
				return PlayerHandler.Exists;
			}
			return true;
		}
	}
	internal sealed class ScoreboardExtensionCells
	{
		private readonly RectTransform _parent;

		private readonly TMP_FontAsset _font;

		private readonly bool _header;

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

		private readonly List<Button> _actionButtons = new List<Button>();

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

		public ScoreboardExtensionCells(RectTransform parent, TMP_FontAsset font, bool header)
		{
			_parent = parent;
			_font = font;
			_header = header;
		}

		public void SyncStructure(ScoreboardLayout layout)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			EnsureColumnCount(layout.Columns.Count);
			EnsureActionCount(layout.RowActions.Count);
			for (int i = 0; i < _columnLabels.Count; i++)
			{
				bool flag = i < layout.Columns.Count;
				((Component)_columnLabels[i]).gameObject.SetActive(flag);
				if (flag)
				{
					ScoreboardColumn scoreboardColumn = layout.Columns[i];
					ScoreboardLayout.Slot slot = layout.ColumnSlots[i];
					TextMeshProUGUI val = _columnLabels[i];
					((TMP_Text)val).text = (_header ? scoreboardColumn.Header : string.Empty);
					((TMP_Text)val).alignment = ToTmp(scoreboardColumn.Alignment);
					ApplySlot(((TMP_Text)val).rectTransform, slot, 4f);
					if (_header)
					{
						((Graphic)val).color = RuntimeUiFactory.TextMuted;
					}
				}
			}
			for (int j = 0; j < _actionButtons.Count; j++)
			{
				bool flag2 = j < layout.RowActions.Count;
				((Component)_actionButtons[j]).gameObject.SetActive(flag2);
				if (flag2)
				{
					ScoreboardRowAction scoreboardRowAction = layout.RowActions[j];
					((TMP_Text)_actionLabels[j]).text = (_header ? string.Empty : scoreboardRowAction.Label);
					PlaceActionButton(((Component)_actionButtons[j]).GetComponent<RectTransform>(), layout, j);
				}
			}
		}

		public void BindHeader(ScoreboardLayout layout)
		{
			SyncStructure(layout);
			for (int i = 0; i < layout.RowActions.Count && i < _actionButtons.Count; i++)
			{
				((Component)_actionButtons[i]).gameObject.SetActive(false);
			}
		}

		public void BindRow(ScoreboardLayout layout, ScoreboardPlayer player)
		{
			//IL_00e1: 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_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Expected O, but got Unknown
			SyncStructure(layout);
			for (int i = 0; i < layout.Columns.Count && i < _columnLabels.Count; i++)
			{
				ScoreboardColumn scoreboardColumn = layout.Columns[i];
				TextMeshProUGUI val = _columnLabels[i];
				try
				{
					((TMP_Text)val).text = scoreboardColumn.GetValue(player) ?? string.Empty;
				}
				catch (Exception ex)
				{
					((TMP_Text)val).text = "!";
					Plugin.Log.LogWarning((object)("Scoreboard column '" + scoreboardColumn.Id + "' failed: " + ex.Message));
				}
				Color? val2 = null;
				try
				{
					val2 = scoreboardColumn.GetColor?.Invoke(player);
				}
				catch (Exception ex2)
				{
					Plugin.Log.LogWarning((object)("Scoreboard column '" + scoreboardColumn.Id + "' color failed: " + ex2.Message));
				}
				((Graphic)val).color = (Color)(((??)val2) ?? RuntimeUiFactory.TextPrimary);
			}
			for (int j = 0; j < layout.RowActions.Count && j < _actionButtons.Count; j++)
			{
				ScoreboardRowAction scoreboardRowAction = layout.RowActions[j];
				Button val3 = _actionButtons[j];
				bool flag = true;
				bool interactable = true;
				try
				{
					flag = scoreboardRowAction.IsVisible?.Invoke(player) ?? true;
				}
				catch (Exception ex3)
				{
					flag = false;
					Plugin.Log.LogWarning((object)("Scoreboard action '" + scoreboardRowAction.Id + "' IsVisible failed: " + ex3.Message));
				}
				if (flag)
				{
					try
					{
						interactable = scoreboardRowAction.IsEnabled?.Invoke(player) ?? true;
					}
					catch (Exception ex4)
					{
						interactable = false;
						Plugin.Log.LogWarning((object)("Scoreboard action '" + scoreboardRowAction.Id + "' IsEnabled failed: " + ex4.Message));
					}
				}
				((Component)val3).gameObject.SetActive(flag);
				((Selectable)val3).interactable = interactable;
				((TMP_Text)_actionLabels[j]).text = scoreboardRowAction.Label;
				((UnityEventBase)val3.onClick).RemoveAllListeners();
				if (flag)
				{
					ScoreboardPlayer captured = player;
					ScoreboardRowAction capturedAction = scoreboardRowAction;
					((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
					{
						try
						{
							capturedAction.OnClick(captured);
						}
						catch (Exception arg)
						{
							Plugin.Log.LogError((object)$"Scoreboard action '{capturedAction.Id}' failed: {arg}");
						}
					});
				}
				PlaceActionButton(((Component)val3).GetComponent<RectTransform>(), layout, j);
			}
		}

		private void EnsureColumnCount(int count)
		{
			//IL_0036: 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)
			while (_columnLabels.Count < count)
			{
				TextMeshProUGUI val = RuntimeUiFactory.CreateText("ExtColumn", (Transform)(object)_parent, _font, _header ? 16f : 20f, _header ? RuntimeUiFactory.TextMuted : RuntimeUiFactory.TextPrimary, (TextAlignmentOptions)514);
				((TMP_Text)val).text = string.Empty;
				((Graphic)val).raycastTarget = false;
				_columnLabels.Add(val);
			}
		}

		private void EnsureActionCount(int count)
		{
			while (_actionButtons.Count < count)
			{
				Button val = RuntimeUiFactory.CreateButton("ExtAction", (Transform)(object)_parent, _font, "");
				TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
				_actionButtons.Add(val);
				_actionLabels.Add(componentInChildren);
				if (_header)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		private static void PlaceActionButton(RectTransform rect, ScoreboardLayout layout, int index)
		{
			//IL_005a: 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_0081: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			int num = Math.Max(1, layout.RowActions.Count + 1);
			float num2 = layout.Actions.Max - layout.Actions.Min;
			float num3 = num2 / (float)num;
			float num4 = layout.Actions.Min + (float)index * num3;
			float num5 = num4 + num3;
			rect.anchorMin = new Vector2(num4, 0.5f);
			rect.anchorMax = new Vector2(num5, 0.5f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.anchoredPosition = Vector2.zero;
			rect.sizeDelta = new Vector2(0f, 36f);
			rect.offsetMin = new Vector2(4f, -18f);
			rect.offsetMax = new Vector2(-4f, 18f);
		}

		internal static void PlaceRespawnButton(RectTransform rect, ScoreboardLayout layout)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			int count = layout.RowActions.Count;
			int num = Math.Max(1, count + 1);
			float num2 = layout.Actions.Max - layout.Actions.Min;
			float num3 = num2 / (float)num;
			float num4 = layout.Actions.Min + (float)count * num3;
			float max = layout.Actions.Max;
			rect.anchorMin = new Vector2(num4, 0.5f);
			rect.anchorMax = new Vector2(max, 0.5f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.anchoredPosition = Vector2.zero;
			rect.sizeDelta = new Vector2(0f, 36f);
			rect.offsetMin = new Vector2(4f, -18f);
			rect.offsetMax = new Vector2(-4f, 18f);
		}

		private static void ApplySlot(RectTransform rect, ScoreboardLayout.Slot slot, float leftPad)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(slot.Min, 0f);
			rect.anchorMax = new Vector2(slot.Max, 1f);
			rect.offsetMin = new Vector2(leftPad, 4f);
			rect.offsetMax = new Vector2(-4f, -4f);
		}

		private static TextAlignmentOptions ToTmp(ScoreboardTextAlign align)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return (TextAlignmentOptions)(align switch
			{
				ScoreboardTextAlign.Left => 4097, 
				ScoreboardTextAlign.Right => 4100, 
				_ => 514, 
			});
		}
	}
	internal sealed class ScoreboardLayout
	{
		public readonly struct Slot
		{
			public float Min { get; }

			public float Max { get; }

			public float Mid => (Min + Max) * 0.5f;

			public Slot(float min, float max)
			{
				Min = min;
				Max = max;
			}
		}

		private const float BuiltInTotalWeight = 90f;

		private const float ActionBaseWeight = 10f;

		private const float ActionExtraWeight = 8f;

		private const float ExtensionUnitWeight = 8f;

		public Slot Scout { get; private set; }

		public Slot State { get; private set; }

		public Slot Stamina { get; private set; }

		public Slot Effects { get; private set; }

		public Slot Height { get; private set; }

		public Slot Travel { get; private set; }

		public Slot Deaths { get; private set; }

		public Slot Actions { get; private set; }

		public IReadOnlyList<ScoreboardColumn> Columns { get; private set; } = Array.Empty<ScoreboardColumn>();

		public IReadOnlyList<ScoreboardRowAction> RowActions { get; private set; } = Array.Empty<ScoreboardRowAction>();

		public IReadOnlyList<Slot> ColumnSlots { get; private set; } = Array.Empty<Slot>();

		public int RegistryVersion { get; private set; } = -1;

		public static ScoreboardLayout Capture()
		{
			ScoreboardLayout scoreboardLayout = new ScoreboardLayout();
			scoreboardLayout.Rebuild(ScoreboardRegistry.SnapshotColumns(), ScoreboardRegistry.SnapshotActions(), ScoreboardRegistry.Version);
			return scoreboardLayout;
		}

		public bool NeedsRebuild(int registryVersion)
		{
			return RegistryVersion != registryVersion;
		}

		public void Rebuild(IReadOnlyList<ScoreboardColumn> columns, IReadOnlyList<ScoreboardRowAction> rowActions, int registryVersion)
		{
			Columns = columns;
			RowActions = rowActions;
			RegistryVersion = registryVersion;
			float num = 0f;
			for (int i = 0; i < columns.Count; i++)
			{
				num += Mathf.Max(0.25f, columns[i].WidthWeight) * 8f;
			}
			float num2 = 10f + (float)rowActions.Count * 8f;
			float num3 = 90f + num + num2;
			if (num3 <= 0f)
			{
				num3 = 100f;
			}
			float cursor = 0f;
			Scout = Take(ref cursor, 22f / num3);
			State = Take(ref cursor, 8f / num3);
			Stamina = Take(ref cursor, 18f / num3);
			Effects = Take(ref cursor, 18f / num3);
			Height = Take(ref cursor, 9f / num3);
			Travel = Take(ref cursor, 9f / num3);
			Deaths = Take(ref cursor, 6f / num3);
			Slot[] array = new Slot[columns.Count];
			for (int j = 0; j < columns.Count; j++)
			{
				float width = Mathf.Max(0.25f, columns[j].WidthWeight) * 8f / num3;
				array[j] = Take(ref cursor, width);
			}
			ColumnSlots = array;
			Actions = new Slot(cursor, 1f);
		}

		private static Slot Take(ref float cursor, float width)
		{
			float min = cursor;
			cursor = Mathf.Min(1f, cursor + width);
			return new Slot(min, cursor);
		}
	}
	internal sealed class ScoreboardView
	{
		private readonly CanvasGroup _canvasGroup;

		private readonly TMP_FontAsset _font;

		private readonly TextMeshProUGUI _subtitle;

		private readonly TextMeshProUGUI _status;

		private readonly RectTransform _panel;

		private readonly RectTransform _rowContent;

		private readonly ScrollRect _scroll;

		private readonly ScoreboardHeaderView _header;

		private readonly List<ScoreboardRowView> _rows = new List<ScoreboardRowView>();

		private ScoreboardLayout _layout = ScoreboardLayout.Capture();

		public GameObject Root { get; }

		public ScoreboardWindow Window { get; }

		public Action? OnCloseRequested { get; set; }

		private ScoreboardView(GameObject root, ScoreboardWindow window, CanvasGroup canvasGroup, TMP_FontAsset font, TextMeshProUGUI subtitle, TextMeshProUGUI status, RectTransform panel, RectTransform rowContent, ScrollRect scroll, ScoreboardHeaderView header)
		{
			Root = root;
			Window = window;
			_canvasGroup = canvasGroup;
			_font = font;
			_subtitle = subtitle;
			_status = status;
			_panel = panel;
			_rowContent = rowContent;
			_scroll = scroll;
			_header = header;
		}

		public static ScoreboardView Create()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: 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_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0575: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_058d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dc: Expected O, but got Unknown
			//IL_068c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Expected O, but got Unknown
			GameObject val = new GameObject("PeakScoreboardUI", new Type[5]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(CanvasGroup),
				typeof(GraphicRaycaster)
			});
			try
			{
				RectTransform component = val.GetComponent<RectTransform>();
				RuntimeUiFactory.Stretch(component);
				Canvas component2 = val.GetComponent<Canvas>();
				component2.renderMode = (RenderMode)0;
				component2.sortingOrder = 240;
				CanvasScaler component3 = val.GetComponent<CanvasScaler>();
				component3.uiScaleMode = (ScaleMode)1;
				component3.referenceResolution = new Vector2(1920f, 1080f);
				component3.screenMatchMode = (ScreenMatchMode)0;
				component3.matchWidthOrHeight = 0.5f;
				TMP_FontAsset font = RuntimeUiFactory.ResolveFont();
				Image val2 = RuntimeUiFactory.CreateImage("Dim", (Transform)(object)component, RuntimeUiFactory.Backdrop);
				RuntimeUiFactory.Stretch(((Graphic)val2).rectTransform);
				((Graphic)val2).raycastTarget = false;
				Image val3 = RuntimeUiFactory.CreateImage("Panel", (Transform)(object)component, RuntimeUiFactory.Panel);
				RectTransform rectTransform = ((Graphic)val3).rectTransform;
				rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
				rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
				rectTransform.pivot = new Vector2(0.5f, 0.5f);
				rectTransform.sizeDelta = new Vector2(1280f, 640f);
				TextMeshProUGUI val4 = RuntimeUiFactory.CreateText("Title", (Transform)(object)rectTransform, font, 34f, RuntimeUiFactory.TextPrimary, (TextAlignmentOptions)4097);
				((TMP_Text)val4).text = "Scoreboard";
				((TMP_Text)val4).rectTransform.anchorMin = new Vector2(0f, 1f);
				((TMP_Text)val4).rectTransform.anchorMax = new Vector2(1f, 1f);
				((TMP_Text)val4).rectTransform.pivot = new Vector2(0.5f, 1f);
				((TMP_Text)val4).rectTransform.anchoredPosition = new Vector2(0f, -18f);
				((TMP_Text)val4).rectTransform.sizeDelta = new Vector2(-140f, 44f);
				Button val5 = RuntimeUiFactory.CreateButton("Close", (Transform)(object)rectTransform, font, "Close");
				RectTransform component4 = ((Component)val5).GetComponent<RectTransform>();
				component4.anchorMin = new Vector2(1f, 1f);
				component4.anchorMax = new Vector2(1f, 1f);
				component4.pivot = new Vector2(1f, 1f);
				component4.anchoredPosition = new Vector2(-24f, -16f);
				component4.sizeDelta = new Vector2(96f, 36f);
				TextMeshProUGUI val6 = RuntimeUiFactory.CreateText("Subtitle", (Transform)(object)rectTransform, font, 18f, RuntimeUiFactory.TextMuted, (TextAlignmentOptions)4097);
				((TMP_Text)val6).text = "Press Scoreboard again or Close · click Respawn on dead scouts";
				((TMP_Text)val6).rectTransform.anchorMin = new Vector2(0f, 1f);
				((TMP_Text)val6).rectTransform.anchorMax = new Vector2(1f, 1f);
				((TMP_Text)val6).rectTransform.pivot = new Vector2(0.5f, 1f);
				((TMP_Text)val6).rectTransform.anchoredPosition = new Vector2(0f, -62f);
				((TMP_Text)val6).rectTransform.sizeDelta = new Vector2(-48f, 28f);
				ScoreboardHeaderView header = ScoreboardHeaderView.Create(rectTransform, font);
				TextMeshProUGUI val7 = RuntimeUiFactory.CreateText("Status", (Transform)(object)rectTransform, font, 17f, RuntimeUiFactory.TextMuted, (TextAlignmentOptions)4097);
				((TMP_Text)val7).text = string.Empty;
				((TMP_Text)val7).rectTransform.anchorMin = new Vector2(0f, 0f);
				((TMP_Text)val7).rectTransform.anchorMax = new Vector2(1f, 0f);
				((TMP_Text)val7).rectTransform.pivot = new Vector2(0.5f, 0f);
				((TMP_Text)val7).rectTransform.anchoredPosition = new Vector2(0f, 16f);
				((TMP_Text)val7).rectTransform.sizeDelta = new Vector2(-48f, 24f);
				RectTransform val8 = RuntimeUiFactory.CreateRect("Rows", (Transform)(object)rectTransform, typeof(ScrollRect));
				val8.anchorMin = Vector2.zero;
				val8.anchorMax = Vector2.one;
				val8.offsetMin = new Vector2(24f, 48f);
				val8.offsetMax = new Vector2(-24f, -132f);
				RectTransform val9 = RuntimeUiFactory.CreateRect("Viewport", (Transform)(object)val8, typeof(Image), typeof(RectMask2D));
				RuntimeUiFactory.Stretch(val9, 0f, 18f);
				((Graphic)((Component)val9).GetComponent<Image>()).color = new Color(1f, 1f, 1f, 0.01f);
				((Graphic)((Component)val9).GetComponent<Image>()).raycastTarget = true;
				RectTransform val10 = RuntimeUiFactory.CreateRect("Content", (Transform)(object)val9, typeof(VerticalLayoutGroup), typeof(ContentSizeFitter));
				val10.anchorMin = new Vector2(0f, 1f);
				val10.anchorMax = new Vector2(1f, 1f);
				val10.pivot = new Vector2(0.5f, 1f);
				val10.anchoredPosition = Vector2.zero;
				val10.sizeDelta = Vector2.zero;
				VerticalLayoutGroup component5 = ((Component)val10).GetComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)component5).spacing = 8f;
				((HorizontalOrVerticalLayoutGroup)component5).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)component5).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component5).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)component5).childForceExpandWidth = true;
				((LayoutGroup)component5).padding = new RectOffset(0, 0, 0, 0);
				((Component)val10).GetComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
				Scrollbar verticalScrollbar = CreateVerticalScrollbar(val8);
				ScrollRect component6 = ((Component)val8).GetComponent<ScrollRect>();
				component6.viewport = val9;
				component6.content = val10;
				component6.horizontal = false;
				component6.vertical = true;
				component6.movementType = (MovementType)2;
				component6.scrollSensitivity = 40f;
				component6.verticalScrollbar = verticalScrollbar;
				component6.verticalScrollbarVisibility = (ScrollbarVisibility)2;
				component6.verticalScrollbarSpacing = 4f;
				ScoreboardWindow window = val.AddComponent<ScoreboardWindow>();
				Object.DontDestroyOnLoad((Object)(object)val);
				ScoreboardView view = new ScoreboardView(val, window, val.GetComponent<CanvasGroup>(), font, val6, val7, rectTransform, val10, component6, header);
				((UnityEven