Decompiled source of LoadingWidgetREPO v1.1.0

LoadingWidgetREPO.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using SharePermissions.Api;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("RED")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+f24bd4d21a83945fba67665512fa40eae241bd04")]
[assembly: AssemblyProduct("LoadingWidgetREPO")]
[assembly: AssemblyTitle("LoadingWidgetREPO")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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 LoadingWidget
{
	internal interface IPanelBackend
	{
		bool ShowLoadingPanel { get; }

		bool LocalCanModerate { get; }

		bool PendingLobbyReturn { get; }

		bool IsMasterOrSingleplayer { get; }

		float VolumeMax { get; }

		int RoleTier(Player? player);

		float VoiceAmplitude(int actorNumber);

		float VolumeFactor(int actorNumber);

		void SetVolume(int actorNumber, float factor);

		string SanitizeName(string? name, string? fallback = "Unknown");

		bool CanKick(PlayerAvatar target);

		bool CanKickActor(Player target);

		void Kick(PlayerAvatar target, bool ban);

		void KickGhost(Player ghost, bool ban);

		void BackToLobby();

		void ForceLobbyReload();

		void Tick();

		void ResetSession();
	}
	internal static class Bridge
	{
		private sealed class InertBackend : IPanelBackend
		{
			public bool ShowLoadingPanel => false;

			public bool LocalCanModerate => false;

			public bool PendingLobbyReturn => false;

			public bool IsMasterOrSingleplayer => false;

			public float VolumeMax => 2f;

			public int RoleTier(Player? player)
			{
				return 0;
			}

			public float VoiceAmplitude(int actorNumber)
			{
				return 0f;
			}

			public float VolumeFactor(int actorNumber)
			{
				return 1f;
			}

			public void SetVolume(int actorNumber, float factor)
			{
			}

			public string SanitizeName(string? name, string? fallback = "Unknown")
			{
				return name ?? fallback ?? "";
			}

			public bool CanKick(PlayerAvatar target)
			{
				return false;
			}

			public bool CanKickActor(Player target)
			{
				return false;
			}

			public void Kick(PlayerAvatar target, bool ban)
			{
			}

			public void KickGhost(Player ghost, bool ban)
			{
			}

			public void BackToLobby()
			{
			}

			public void ForceLobbyReload()
			{
			}

			public void Tick()
			{
			}

			public void ResetSession()
			{
			}
		}

		private static IPanelBackend active = new InertBackend();

		internal static bool ShowLoadingPanel => active.ShowLoadingPanel;

		internal static bool LocalCanModerate => active.LocalCanModerate;

		internal static bool PendingLobbyReturn => active.PendingLobbyReturn;

		internal static bool IsMasterOrSingleplayer => active.IsMasterOrSingleplayer;

		internal static float VolumeMax => active.VolumeMax;

		internal static void Select(IPanelBackend backend)
		{
			active = backend;
		}

		internal static int RoleTier(Player? player)
		{
			return active.RoleTier(player);
		}

		internal static float VoiceAmplitude(int actorNumber)
		{
			return active.VoiceAmplitude(actorNumber);
		}

		internal static float VolumeFactor(int actorNumber)
		{
			return active.VolumeFactor(actorNumber);
		}

		internal static void SetVolume(int actorNumber, float factor)
		{
			active.SetVolume(actorNumber, factor);
		}

		internal static string SanitizeName(string? name, string? fallback = "Unknown")
		{
			return active.SanitizeName(name, fallback);
		}

		internal static bool CanKick(PlayerAvatar target)
		{
			return active.CanKick(target);
		}

		internal static bool CanKickActor(Player target)
		{
			return active.CanKickActor(target);
		}

		internal static void Kick(PlayerAvatar target, bool ban)
		{
			active.Kick(target, ban);
		}

		internal static void KickGhost(Player ghost, bool ban)
		{
			active.KickGhost(ghost, ban);
		}

		internal static void BackToLobby()
		{
			active.BackToLobby();
		}

		internal static void ForceLobbyReload()
		{
			active.ForceLobbyReload();
		}

		internal static void Tick()
		{
			active.Tick();
		}

		internal static void ResetSession()
		{
			active.ResetSession();
		}
	}
	[HarmonyPatch(typeof(NetworkConnect), "OnDisconnected")]
	internal static class DisconnectReset
	{
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void OnDisconnected_Postfix()
		{
			LoadingPanel.ResetSession();
			Bridge.ResetSession();
		}
	}
	internal sealed class LoadingPanel : MonoBehaviour
	{
		private enum LoadState
		{
			Loading,
			Generating,
			Loaded,
			Ready
		}

		private sealed class TextButton
		{
			internal readonly GameObject Go;

			internal readonly RectTransform Rect;

			private readonly TMP_Text tmp;

			private float clickFlashUntil;

			private string label = "";

			internal bool Danger;

			internal string Label
			{
				get
				{
					return label;
				}
				set
				{
					if (label != value)
					{
						label = value;
						tmp.text = value;
					}
				}
			}

			internal TextButton(GameObject go, TMP_Text tmp)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				Go = go;
				Rect = (RectTransform)go.transform;
				this.tmp = tmp;
			}

			internal void SetVisible(bool visible)
			{
				SetActiveIfChanged(Go, visible);
			}

			internal bool Tick(ref bool anyHover, Image? hoverFill)
			{
				//IL_0027: 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_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				bool hovered;
				bool flashing;
				bool result = TickHit(Go, Rect, ref clickFlashUntil, ref anyHover, hoverFill, out hovered, out flashing);
				if (flashing)
				{
					((Graphic)tmp).color = LoadingWidgetStyle.NativeBtnClick;
				}
				else if (hovered)
				{
					((Graphic)tmp).color = (Danger ? LoadingWidgetStyle.DangerTextHover : LoadingWidgetStyle.NativeBtnHover);
				}
				else
				{
					((Graphic)tmp).color = (Danger ? LoadingWidgetStyle.DangerText : LoadingWidgetStyle.NativeBtnIdle);
				}
				return result;
			}
		}

		private sealed class IconButton
		{
			internal readonly GameObject Go;

			internal readonly RectTransform Rect;

			private readonly GameObject kebab;

			private readonly GameObject close;

			private readonly Image[] kebabParts;

			private readonly Image[] closeParts;

			private float clickFlashUntil;

			private bool expanded;

			internal IconButton(GameObject go, GameObject kebab, Image[] kebabParts, GameObject close, Image[] closeParts)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				Go = go;
				Rect = (RectTransform)go.transform;
				this.kebab = kebab;
				this.kebabParts = kebabParts;
				this.close = close;
				this.closeParts = closeParts;
				SetExpanded(value: false);
			}

			internal void SetVisible(bool visible)
			{
				SetActiveIfChanged(Go, visible);
			}

			internal void SetExpanded(bool value)
			{
				expanded = value;
				SetActiveIfChanged(kebab, !value);
				SetActiveIfChanged(close, value);
			}

			internal bool Tick(ref bool anyHover, Image? hoverFill)
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				bool hovered;
				bool flashing;
				bool result = TickHit(Go, Rect, ref clickFlashUntil, ref anyHover, hoverFill, out hovered, out flashing);
				Color color = (flashing ? LoadingWidgetStyle.NativeBtnClick : (hovered ? LoadingWidgetStyle.NativeBtnHover : LoadingWidgetStyle.NativeBtnIdle));
				Image[] array = (expanded ? closeParts : kebabParts);
				Image[] array2 = array;
				foreach (Image val in array2)
				{
					((Graphic)val).color = color;
				}
				return result;
			}
		}

		private sealed class RowWidget
		{
			internal const float BarW = 130f;

			internal const float BarH = 12f;

			internal GameObject Go;

			internal RectTransform Rect;

			internal readonly GameObject?[] RoleIcons = (GameObject?[])(object)new GameObject[4];

			internal TMP_Text State;

			internal TMP_Text Name;

			internal Image BarTrack;

			internal Image BarFill;

			internal IconButton More;

			private int lastTier = -1;

			internal float LastY = float.NaN;

			internal float LastBarW;

			internal int LastNameActor = -1;

			internal string? LastRawName;

			internal bool LastIsLocal;

			internal void SetVisible(bool visible)
			{
				SetActiveIfChanged(Go, visible);
			}

			internal void SetTier(int tier)
			{
				if (tier == lastTier)
				{
					return;
				}
				lastTier = tier;
				for (int i = 0; i < RoleIcons.Length; i++)
				{
					GameObject val = RoleIcons[i];
					if ((Object)(object)val != (Object)null)
					{
						SetActiveIfChanged(val, i == tier);
					}
				}
			}
		}

		private sealed class ExpansionWidget
		{
			internal const float TrackW = 220f;

			internal const float TrackH = 10f;

			internal GameObject Go;

			internal RectTransform Rect;

			internal TextButton Kick;

			internal TextButton Ban;

			internal Image SliderTrack;

			internal Image SliderFill;

			internal RectTransform SliderHit;

			internal RectTransform Thumb;

			internal TMP_Text Percent;

			internal float LastFill = -1f;

			internal int LastPercent = -1;

			internal void SetVisible(bool visible)
			{
				SetActiveIfChanged(Go, visible);
			}
		}

		private static LoadingPanel? instance;

		private const float LobbyArmSeconds = 3f;

		private const float LoudnessScale = 5f;

		private const float SmoothSpeed = 12f;

		private const float ClickFlashSeconds = 0.12f;

		private const float ReloadSearchSeconds = 0.25f;

		private const float FontRetrySeconds = 0.5f;

		private const float PanelStuckSeconds = 35f;

		private const int MaxRows = 20;

		private const float PanelW = 620f;

		private const float RowH = 42f;

		private const float HeaderH = 52f;

		private const float Pad = 16f;

		private const float FontHeader = 30f;

		private const float FontRow = 24f;

		private const float FontSmall = 18f;

		private static bool windowOpen;

		private static readonly Dictionary<int, float> Loudness = new Dictionary<int, float>();

		private static int expandedActor = -1;

		private static float lobbyArmedUntil;

		private static int lastBailMode;

		private static int sliderDragActor = -1;

		private static int lastHeaderLoaded = -1;

		private static int lastHeaderTotal = -1;

		private static bool lastHeaderStuck;

		private static readonly Dictionary<int, PlayerAvatar> ActorAvatars = new Dictionary<int, PlayerAvatar>();

		private static readonly HashSet<int> SceneLoadedActors = new HashSet<int>();

		private static readonly HashSet<int> SpawnedReadyActors = new HashSet<int>();

		private static readonly HashSet<int> EnemyReadyActors = new HashSet<int>();

		private static readonly HashSet<int> ReloadReadyActors = new HashSet<int>();

		private static bool levelGeneratorPresent;

		private static bool levelGenerated;

		private static bool levelHasEnemies;

		private static bool gameStuck;

		private static bool loadStuck;

		private static float windowOpenSince = -1f;

		private static bool reloadScenePresent;

		private static bool outroInFlight;

		private static bool inReloadGap;

		private static ReloadScene? reloadSceneCache;

		private static float nextReloadSearchTime;

		private GameObject? root;

		private Canvas? canvas;

		private RectTransform? panelRect;

		private TMP_Text? headerText;

		private TextButton? lobbyButton;

		private Image? hoverFill;

		private RectTransform? cursorRect;

		private readonly RowWidget[] rows = new RowWidget[20];

		private readonly LoadState[] frameStates = new LoadState[20];

		private ExpansionWidget? expansion;

		private static TMP_FontAsset? gameFont;

		private static float nextFontAttemptTime;

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

		private static bool updateFaulted;

		private static float nextDiagTime;

		private static int outroEndValue;

		private static int outroEndWaitValue;

		private static bool outroEnumResolved;

		private static bool outroTierAlive;

		internal static void Init()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (!((Object)(object)instance != (Object)null))
			{
				GameObject val = new GameObject("LoadingWidgetPanel")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)val);
				instance = val.AddComponent<LoadingPanel>();
			}
		}

		private void Awake()
		{
			BuildUi();
		}

		private void Update()
		{
			Bridge.Tick();
			try
			{
				UpdateCore();
			}
			catch (Exception arg)
			{
				if ((Object)(object)root != (Object)null && root.activeSelf)
				{
					root.SetActive(false);
				}
				if ((Object)(object)cursorRect != (Object)null && ((Component)cursorRect).gameObject.activeSelf)
				{
					((Component)cursorRect).gameObject.SetActive(false);
				}
				if (!updateFaulted)
				{
					updateFaulted = true;
					Plugin.Logger.LogWarning((object)$"LoadingPanel update failed (bridge or game drift?) - panel hidden: {arg}");
				}
			}
		}

		private void UpdateCore()
		{
			bool flag = Bridge.ShowLoadingPanel && IsLevelLoading();
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			SetActiveIfChanged(root, flag);
			if ((Object)(object)cursorRect != (Object)null)
			{
				SetActiveIfChanged(((Component)cursorRect).gameObject, flag);
			}
			if (!flag)
			{
				sliderDragActor = -1;
				lobbyArmedUntil = 0f;
				expandedActor = -1;
				windowOpenSince = -1f;
				Loudness.Clear();
				return;
			}
			try
			{
				CursorUnlockRaw();
			}
			catch
			{
			}
			try
			{
				DisablePlayerInputRaw();
			}
			catch
			{
			}
			EnsureFont();
			ActorAvatars.Clear();
			try
			{
				BuildActorAvatarMap();
			}
			catch
			{
			}
			BuildLoadSnapshot();
			Player[] playerList = PhotonNetwork.PlayerList;
			SmoothLoudness(playerList);
			SyncAndDraw(playerList);
			UpdateCursor();
		}

		private void SmoothLoudness(Player[] players)
		{
			float num = Time.deltaTime * 12f;
			foreach (Player val in players)
			{
				float num2 = Mathf.Clamp01(Bridge.VoiceAmplitude(val.ActorNumber) * 5f);
				Loudness.TryGetValue(val.ActorNumber, out var value);
				Loudness[val.ActorNumber] = Mathf.Lerp(value, num2, num);
			}
		}

		private void SyncAndDraw(Player[] players)
		{
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: 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_0396: Unknown result type (might be due to invalid IL or missing references)
			bool anyHover = false;
			LogDiagnostics(players);
			int num = 0;
			for (int i = 0; i < players.Length; i++)
			{
				LoadState loadState = StateOf(players[i].ActorNumber);
				if (i < 20)
				{
					frameStates[i] = loadState;
				}
				if (loadState == LoadState.Loaded || loadState == LoadState.Ready)
				{
					num++;
				}
			}
			if (num != lastHeaderLoaded || players.Length != lastHeaderTotal || loadStuck != lastHeaderStuck)
			{
				lastHeaderLoaded = num;
				lastHeaderTotal = players.Length;
				lastHeaderStuck = loadStuck;
				string text = (loadStuck ? "#F0736B" : "#FF8500");
				string text2 = (loadStuck ? string.Format("  <size={0}><color={1}>STUCK</color></size>", 18, "#F0736B") : "");
				SetText(headerText, $"PLAYERS LOADED  <color={text}>{num}/{players.Length}</color>{text2}");
			}
			if (lobbyButton != null)
			{
				bool localCanModerate = Bridge.LocalCanModerate;
				lobbyButton.SetVisible(localCanModerate);
				if (!localCanModerate)
				{
					lobbyArmedUntil = 0f;
				}
				else
				{
					bool pendingLobbyReturn = Bridge.PendingLobbyReturn;
					int num2 = ((pendingLobbyReturn && Bridge.IsMasterOrSingleplayer) ? 1 : (pendingLobbyReturn ? 2 : 0));
					if (num2 != lastBailMode)
					{
						lobbyArmedUntil = 0f;
						lastBailMode = num2;
					}
					bool flag = num2 != 2 && Time.time < lobbyArmedUntil;
					if (!flag)
					{
						lobbyArmedUntil = 0f;
					}
					lobbyButton.Danger = num2 == 1 || flag || loadStuck;
					TextButton textButton = lobbyButton;
					textButton.Label = num2 switch
					{
						1 => flag ? "FORCE?" : "FORCE", 
						2 => "QUEUED", 
						_ => flag ? "LOBBY?" : "LOBBY", 
					};
					if (lobbyButton.Tick(ref anyHover, hoverFill) && num2 != 2)
					{
						if (!flag)
						{
							lobbyArmedUntil = Time.time + 3f;
						}
						else
						{
							lobbyArmedUntil = 0f;
							if (num2 == 1)
							{
								Bridge.ForceLobbyReload();
							}
							else
							{
								Bridge.BackToLobby();
							}
						}
					}
				}
			}
			int num3 = Mathf.Min(players.Length, 20);
			bool flag2 = false;
			int num4 = -1;
			for (int j = 0; j < num3; j++)
			{
				if (players[j].ActorNumber == expandedActor)
				{
					flag2 = true;
					num4 = j;
					break;
				}
			}
			if (!flag2)
			{
				expandedActor = -1;
			}
			float num5 = 68f + (float)num3 * 42f + (flag2 ? 42f : 0f) + 16f;
			if ((Object)(object)panelRect != (Object)null && !Mathf.Approximately(panelRect.sizeDelta.y, num5))
			{
				panelRect.sizeDelta = new Vector2(620f, num5);
			}
			float num6 = -68f;
			for (int k = 0; k < 20; k++)
			{
				RowWidget rowWidget = rows[k];
				bool flag3 = k < num3;
				rowWidget.SetVisible(flag3);
				if (flag3)
				{
					Player p = players[k];
					bool flag4 = k == num4;
					if (rowWidget.LastY != num6)
					{
						rowWidget.LastY = num6;
						rowWidget.Rect.anchoredPosition = new Vector2(0f, num6);
					}
					DrawRow(rowWidget, p, frameStates[k], flag4, ref anyHover);
					num6 -= 42f;
					if (flag4 && expansion != null)
					{
						expansion.Rect.anchoredPosition = new Vector2(0f, num6);
						DrawExpansion(p, ref anyHover);
						num6 -= 42f;
					}
				}
			}
			expansion?.SetVisible(flag2);
			if (!anyHover && (Object)(object)hoverFill != (Object)null)
			{
				((Behaviour)hoverFill).enabled = false;
			}
		}

		private void DrawRow(RowWidget row, Player p, LoadState state, bool expanded, ref bool anyHover)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			int actorNumber = p.ActorNumber;
			ActorAvatars.TryGetValue(actorNumber, out PlayerAvatar value);
			row.SetTier(Bridge.RoleTier(p));
			SetText(row.State, StateLabel(state));
			((Graphic)row.State).color = StateColor(state, loadStuck && IsBlocking(state));
			string text = NameOf(value, p);
			if (row.LastNameActor != actorNumber || row.LastIsLocal != p.IsLocal || row.LastRawName != text)
			{
				row.LastNameActor = actorNumber;
				row.LastIsLocal = p.IsLocal;
				row.LastRawName = text;
				string text2 = Bridge.SanitizeName(text, $"Player_{actorNumber}");
				SetText(row.Name, p.IsLocal ? (text2 + " <color=#9aa4ad>(you)</color>") : text2);
			}
			((Behaviour)row.BarTrack).enabled = !expanded;
			((Behaviour)row.BarFill).enabled = !expanded;
			if (!expanded)
			{
				Loudness.TryGetValue(actorNumber, out var value2);
				if (value2 < 0.005f)
				{
					value2 = 0f;
				}
				float num = 130f * Mathf.Clamp01(value2);
				if (row.LastBarW != num)
				{
					row.LastBarW = num;
					((Graphic)row.BarFill).rectTransform.sizeDelta = new Vector2(num, 12f);
				}
				((Graphic)row.BarFill).color = ((value2 > 0.02f) ? LoadingWidgetStyle.GetVolumeColor(value2) : Color.clear);
			}
			row.More.SetVisible(!p.IsLocal);
			row.More.SetExpanded(expanded);
			if (!p.IsLocal && row.More.Tick(ref anyHover, hoverFill))
			{
				expandedActor = (expanded ? (-1) : actorNumber);
			}
		}

		private void DrawExpansion(Player p, ref bool anyHover)
		{
			//IL_018b: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			if (expansion == null)
			{
				return;
			}
			int actorNumber = p.ActorNumber;
			ActorAvatars.TryGetValue(actorNumber, out PlayerAvatar value);
			bool flag = (((Object)(object)value != (Object)null) ? Bridge.CanKick(value) : Bridge.CanKickActor(p));
			expansion.Kick.SetVisible(flag);
			expansion.Ban.SetVisible(flag);
			if (flag)
			{
				if (expansion.Kick.Tick(ref anyHover, hoverFill))
				{
					DoKick(p, value, ban: false);
				}
				if (expansion.Ban.Tick(ref anyHover, hoverFill))
				{
					DoKick(p, value, ban: true);
				}
			}
			float num = Bridge.VolumeFactor(actorNumber);
			RectTransform rectTransform = ((Graphic)expansion.SliderTrack).rectTransform;
			if (Input.GetMouseButtonDown(0) && Hovered(expansion.SliderHit))
			{
				sliderDragActor = actorNumber;
			}
			if (sliderDragActor == actorNumber)
			{
				Vector2 val = default(Vector2);
				if (!Input.GetMouseButton(0))
				{
					sliderDragActor = -1;
				}
				else if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, Vector2.op_Implicit(Input.mousePosition), (Camera)null, ref val))
				{
					float x = val.x;
					Rect rect = rectTransform.rect;
					float num2 = x - ((Rect)(ref rect)).xMin;
					rect = rectTransform.rect;
					float num3 = Mathf.Clamp01(num2 / ((Rect)(ref rect)).width);
					num = num3 * Bridge.VolumeMax;
					Bridge.SetVolume(actorNumber, num);
				}
			}
			float num4 = Mathf.Clamp01(num / Bridge.VolumeMax);
			if (expansion.LastFill != num4)
			{
				expansion.LastFill = num4;
				((Graphic)expansion.SliderFill).rectTransform.sizeDelta = new Vector2(220f * num4, 10f);
				expansion.Thumb.anchoredPosition = new Vector2(220f * num4, 0f);
			}
			int num5 = Mathf.RoundToInt(num * 100f);
			if (expansion.LastPercent != num5)
			{
				expansion.LastPercent = num5;
				SetText(expansion.Percent, $"{num5}%");
			}
		}

		private static void DoKick(Player p, PlayerAvatar? avatar, bool ban)
		{
			expandedActor = -1;
			if ((Object)(object)avatar != (Object)null)
			{
				Bridge.Kick(avatar, ban);
			}
			else
			{
				Bridge.KickGhost(p, ban);
			}
		}

		private void UpdateCursor()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cursorRect == (Object)null))
			{
				float num = (((Object)(object)canvas != (Object)null) ? canvas.scaleFactor : 1f);
				cursorRect.anchoredPosition = Vector2.op_Implicit(Input.mousePosition) / num;
			}
		}

		private static bool Hovered(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return RectTransformUtility.RectangleContainsScreenPoint(rt, Vector2.op_Implicit(Input.mousePosition), (Camera)null);
		}

		private static void SetActiveIfChanged(GameObject go, bool value)
		{
			if (go.activeSelf != value)
			{
				go.SetActive(value);
			}
		}

		private static bool TickHit(GameObject go, RectTransform rect, ref float clickFlashUntil, ref bool anyHover, Image? hoverFill, out bool hovered, out bool flashing)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			hovered = go.activeSelf && Hovered(rect);
			bool flag = hovered && Input.GetMouseButtonDown(0);
			if (flag)
			{
				clickFlashUntil = Time.unscaledTime + 0.12f;
			}
			flashing = Time.unscaledTime < clickFlashUntil;
			if (hovered && (Object)(object)hoverFill != (Object)null)
			{
				anyHover = true;
				((Behaviour)hoverFill).enabled = true;
				RectTransform rectTransform = ((Graphic)hoverFill).rectTransform;
				((Transform)rectTransform).position = ((Transform)rect).position;
				rectTransform.sizeDelta = rect.sizeDelta + new Vector2(8f, 4f);
				rectTransform.anchoredPosition += new Vector2(-4f, 2f);
			}
			return flag;
		}

		private void BuildUi()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Canvas");
			val.transform.SetParent(((Component)this).transform, false);
			canvas = val.AddComponent<Canvas>();
			canvas.renderMode = (RenderMode)0;
			canvas.sortingOrder = 32700;
			CanvasScaler val2 = val.AddComponent<CanvasScaler>();
			val2.uiScaleMode = (ScaleMode)1;
			val2.referenceResolution = new Vector2(1920f, 1080f);
			val2.matchWidthOrHeight = 1f;
			root = new GameObject("Panel");
			root.transform.SetParent(val.transform, false);
			panelRect = root.AddComponent<RectTransform>();
			panelRect.sizeDelta = new Vector2(620f, 200f);
			MakeImage(root, new Color(0f, 0f, 0f, 0.35f));
			hoverFill = MakeImage(Child(root, "HoverFill", new Vector2(0f, 0f), new Vector2(10f, 10f)), LoadingWidgetStyle.NativeHoverFill);
			((Behaviour)hoverFill).enabled = false;
			headerText = MakeText(Child(root, "Header", TopLeft(20f, -16f), new Vector2(455f, 52f)), 30f, (TextAlignmentOptions)4097);
			((Graphic)headerText).color = Color.white;
			headerText.characterSpacing = 4f;
			lobbyButton = MakeButton(root, "Lobby", TopLeft(484f, -22f), new Vector2(120f, 34f), 20f);
			for (int i = 0; i < 20; i++)
			{
				rows[i] = BuildRow(i);
			}
			expansion = BuildExpansion();
			GameObject val3 = Child(val, "Cursor", Vector2.zero, new Vector2(14f, 14f));
			RectTransform val4 = (RectTransform)val3.transform;
			Vector2 anchorMin = (val4.anchorMax = Vector2.zero);
			val4.anchorMin = anchorMin;
			val4.pivot = new Vector2(0.5f, 0.5f);
			((Transform)val4).localRotation = Quaternion.Euler(0f, 0f, 45f);
			MakeImage(val3, new Color(0f, 0f, 0f, 0.9f));
			GameObject go = Child(val3, "Inner", new Vector2(3f, -3f), new Vector2(8f, 8f));
			MakeImage(go, Color.white);
			cursorRect = val4;
			val3.SetActive(false);
			root.SetActive(false);
		}

		private RowWidget BuildRow(int index)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00ba: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: 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_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			RowWidget rowWidget = new RowWidget();
			rowWidget.Go = Child(root, $"Row{index}", TopLeft(0f, 0f), new Vector2(620f, 42f));
			rowWidget.Rect = (RectTransform)rowWidget.Go.transform;
			Vector2 center = default(Vector2);
			((Vector2)(ref center))..ctor(31f, -21f);
			rowWidget.RoleIcons[0] = BuildRoleIcon(rowWidget.Go, center, 9f, LoadingWidgetStyle.RoleNone, pip: false);
			rowWidget.RoleIcons[1] = BuildRoleIcon(rowWidget.Go, center, 13f, LoadingWidgetStyle.RoleModUser, pip: false);
			rowWidget.RoleIcons[2] = BuildRoleIcon(rowWidget.Go, center, 16f, LoadingWidgetStyle.RoleModerator, pip: false);
			rowWidget.RoleIcons[3] = BuildRoleIcon(rowWidget.Go, center, 19f, LoadingWidgetStyle.RoleHost, pip: true);
			GameObject[] roleIcons = rowWidget.RoleIcons;
			foreach (GameObject val in roleIcons)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(false);
				}
			}
			rowWidget.Name = MakeText(Child(rowWidget.Go, "Name", TopLeft(48f, 0f), new Vector2(230f, 42f)), 24f, (TextAlignmentOptions)4097);
			((Graphic)rowWidget.Name).color = Color.white;
			rowWidget.State = MakeText(Child(rowWidget.Go, "State", TopLeft(280f, 0f), new Vector2(130f, 42f)), 18f, (TextAlignmentOptions)4097);
			rowWidget.State.characterSpacing = 2f;
			rowWidget.BarTrack = MakeImage(Child(rowWidget.Go, "BarTrack", TopLeft(420f, -15f), new Vector2(130f, 12f)), LoadingWidgetStyle.BarTrack);
			GameObject val2 = Child(rowWidget.Go, "BarFill", TopLeft(420f, -15f), new Vector2(0f, 12f));
			RectTransform val3 = (RectTransform)val2.transform;
			val3.pivot = new Vector2(0f, 1f);
			rowWidget.BarFill = MakeImage(val2, Color.clear);
			rowWidget.More = BuildIconButton(rowWidget.Go, TopLeft(568f, -4f), new Vector2(36f, 34f));
			return rowWidget;
		}

		private ExpansionWidget BuildExpansion()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0066: 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)
			//IL_00b5: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0142: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Expected O, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: 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_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			ExpansionWidget expansionWidget = new ExpansionWidget();
			expansionWidget.Go = Child(root, "Expansion", TopLeft(0f, 0f), new Vector2(620f, 42f));
			expansionWidget.Rect = (RectTransform)expansionWidget.Go.transform;
			TMP_Text val = MakeText(Child(expansionWidget.Go, "VolLabel", TopLeft(46f, 0f), new Vector2(100f, 42f)), 18f, (TextAlignmentOptions)4097);
			val.text = "VOLUME";
			val.characterSpacing = 2f;
			((Graphic)val).color = new Color(0.55f, 0.6f, 0.64f);
			float y = -16f;
			expansionWidget.SliderTrack = MakeImage(Child(expansionWidget.Go, "Track", TopLeft(160f, y), new Vector2(220f, 10f)), LoadingWidgetStyle.BarTrack);
			GameObject val2 = Child(((Component)expansionWidget.SliderTrack).gameObject, "Fill", Vector2.zero, new Vector2(0f, 10f));
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(0f, 0.5f);
			val3.anchorMax = new Vector2(0f, 0.5f);
			val3.pivot = new Vector2(0f, 0.5f);
			val3.anchoredPosition = Vector2.zero;
			expansionWidget.SliderFill = MakeImage(val2, LoadingWidgetStyle.NativeAccent);
			GameObject val4 = Child(((Component)expansionWidget.SliderTrack).gameObject, "Thumb", Vector2.zero, new Vector2(12f, 20f));
			RectTransform val5 = (RectTransform)val4.transform;
			val5.anchorMin = new Vector2(0f, 0.5f);
			val5.anchorMax = new Vector2(0f, 0.5f);
			val5.pivot = new Vector2(0.5f, 0.5f);
			MakeImage(val4, Color.white);
			expansionWidget.Thumb = val5;
			expansionWidget.SliderHit = (RectTransform)Child(expansionWidget.Go, "TrackHit", TopLeft(160f, 0f), new Vector2(220f, 42f)).transform;
			expansionWidget.Percent = MakeText(Child(expansionWidget.Go, "Percent", TopLeft(392f, 0f), new Vector2(70f, 42f)), 18f, (TextAlignmentOptions)4097);
			((Graphic)expansionWidget.Percent).color = Color.white;
			expansionWidget.Kick = MakeButton(expansionWidget.Go, "KICK", TopLeft(460f, -4f), new Vector2(70f, 34f), 18f);
			expansionWidget.Kick.Danger = true;
			expansionWidget.Ban = MakeButton(expansionWidget.Go, "BAN", TopLeft(536f, -4f), new Vector2(60f, 34f), 18f);
			expansionWidget.Ban.Danger = true;
			expansionWidget.Go.SetActive(false);
			return expansionWidget;
		}

		private static Vector2 TopLeft(float x, float y)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(x, y);
		}

		private static GameObject Child(GameObject parent, string name, Vector2 pos, Vector2 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: 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_0055: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 1f);
			val2.anchoredPosition = pos;
			val2.sizeDelta = size;
			return val;
		}

		private static Image MakeImage(GameObject go, Color color)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Image val = go.AddComponent<Image>();
			((Graphic)val).color = color;
			((Graphic)val).raycastTarget = false;
			return val;
		}

		private TMP_Text MakeText(GameObject go, float size, TextAlignmentOptions align)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = go.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val).fontSize = size;
			((TMP_Text)val).alignment = align;
			((TMP_Text)val).richText = true;
			((Graphic)val).raycastTarget = false;
			((TMP_Text)val).enableWordWrapping = false;
			((TMP_Text)val).overflowMode = (TextOverflowModes)1;
			if ((Object)(object)gameFont != (Object)null)
			{
				((TMP_Text)val).font = gameFont;
			}
			allTexts.Add((TMP_Text)(object)val);
			return (TMP_Text)(object)val;
		}

		private TextButton MakeButton(GameObject parent, string label, Vector2 pos, Vector2 size, float fontSize)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			GameObject go = Child(parent, "Btn_" + label, pos, size);
			TMP_Text tmp = MakeText(go, fontSize, (TextAlignmentOptions)4098);
			return new TextButton(go, tmp)
			{
				Label = label
			};
		}

		private static GameObject CenteredChild(GameObject parent, string name, Vector2 center, Vector2 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: 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_0055: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = center;
			val2.sizeDelta = size;
			return val;
		}

		private static GameObject InnerGlyph(GameObject parent, string name, Vector2 offset, Vector2 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: 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_0055: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = new Vector2(0.5f, 0.5f);
			val2.anchorMax = new Vector2(0.5f, 0.5f);
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = offset;
			val2.sizeDelta = size;
			return val;
		}

		private static GameObject FillChild(GameObject parent, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			val2.pivot = new Vector2(0.5f, 0.5f);
			return val;
		}

		private GameObject BuildRoleIcon(GameObject parent, Vector2 center, float size, Color color, bool pip)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CenteredChild(parent, "RoleIcon", center, new Vector2(size, size));
			val.transform.localRotation = Quaternion.Euler(0f, 0f, 45f);
			MakeImage(val, color);
			if (pip)
			{
				GameObject go = InnerGlyph(val, "Pip", Vector2.zero, new Vector2(size * 0.42f, size * 0.42f));
				MakeImage(go, new Color(1f, 1f, 1f, 0.92f));
			}
			return val;
		}

		private IconButton BuildIconButton(GameObject parent, Vector2 pos, Vector2 size)
		{
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Child(parent, "Btn_More", pos, size);
			GameObject val2 = FillChild(val, "Kebab");
			Image[] array = (Image[])(object)new Image[3];
			for (int i = 0; i < 3; i++)
			{
				GameObject go = InnerGlyph(val2, $"Dot{i}", new Vector2(0f, (float)(1 - i) * 7f), new Vector2(5f, 5f));
				array[i] = MakeImage(go, LoadingWidgetStyle.NativeBtnIdle);
			}
			GameObject val3 = FillChild(val, "Close");
			Image[] array2 = (Image[])(object)new Image[2];
			for (int j = 0; j < 2; j++)
			{
				GameObject val4 = InnerGlyph(val3, $"Bar{j}", Vector2.zero, new Vector2(18f, 3f));
				val4.transform.localRotation = Quaternion.Euler(0f, 0f, (j == 0) ? 45f : (-45f));
				array2[j] = MakeImage(val4, LoadingWidgetStyle.NativeBtnIdle);
			}
			return new IconButton(val, val2, array, val3, array2);
		}

		private static void SetText(TMP_Text? tmp, string text)
		{
			if ((Object)(object)tmp != (Object)null && tmp.text != text)
			{
				tmp.text = text;
			}
		}

		private void EnsureFont()
		{
			if ((Object)(object)gameFont != (Object)null || Time.unscaledTime < nextFontAttemptTime)
			{
				return;
			}
			nextFontAttemptTime = Time.unscaledTime + 0.5f;
			try
			{
				gameFont = ResolveFontRaw();
			}
			catch
			{
			}
			if ((Object)(object)gameFont == (Object)null)
			{
				try
				{
					gameFont = ResolveFontFallbackRaw();
				}
				catch
				{
				}
			}
			if ((Object)(object)gameFont == (Object)null)
			{
				return;
			}
			foreach (TMP_Text allText in allTexts)
			{
				if ((Object)(object)allText != (Object)null)
				{
					allText.font = gameFont;
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static TMP_FontAsset? ResolveFontRaw()
		{
			LoadingUI val = LoadingUI.instance;
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if ((Object)(object)val.levelNumberText != (Object)null && (Object)(object)((TMP_Text)val.levelNumberText).font != (Object)null)
			{
				return ((TMP_Text)val.levelNumberText).font;
			}
			if ((Object)(object)val.levelNameText != (Object)null && (Object)(object)((TMP_Text)val.levelNameText).font != (Object)null)
			{
				return ((TMP_Text)val.levelNameText).font;
			}
			return null;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static TMP_FontAsset? ResolveFontFallbackRaw()
		{
			MenuManager val = MenuManager.instance;
			if ((Object)(object)val == (Object)null || val.menuPages == null)
			{
				return null;
			}
			foreach (MenuPages menuPage in val.menuPages)
			{
				if (menuPage != null && !((Object)(object)menuPage.menuPage == (Object)null))
				{
					TMP_Text componentInChildren = menuPage.menuPage.GetComponentInChildren<TMP_Text>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.font != (Object)null)
					{
						return componentInChildren.font;
					}
				}
			}
			return null;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void CursorUnlockRaw()
		{
			SemiFunc.CursorUnlock(0.1f);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool RunIsLobbyMenuRaw()
		{
			return SemiFunc.RunIsLobbyMenu();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool MenuLevelRaw()
		{
			return SemiFunc.MenuLevel();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void DisablePlayerInputRaw()
		{
			PlayerController val = PlayerController.instance;
			if ((Object)(object)val != (Object)null)
			{
				val.InputDisableTimer = 0.1f;
			}
		}

		private static LoadState StateOf(int actor)
		{
			if (reloadScenePresent)
			{
				if (!ReloadReadyActors.Contains(actor))
				{
					return LoadState.Loading;
				}
				return LoadState.Loaded;
			}
			ActorAvatars.TryGetValue(actor, out PlayerAvatar value);
			if (!SceneLoadedActors.Contains(actor) && !((Object)(object)value != (Object)null))
			{
				return LoadState.Loading;
			}
			if (outroInFlight && (Object)(object)value != (Object)null)
			{
				try
				{
					if (!AvatarOutroDone(value))
					{
						return LoadState.Loading;
					}
				}
				catch
				{
				}
			}
			try
			{
				if ((Object)(object)value != (Object)null && AvatarReady(value))
				{
					return LoadState.Ready;
				}
			}
			catch
			{
			}
			if (levelGeneratorPresent && !levelGenerated)
			{
				if (!SpawnedReadyActors.Contains(actor))
				{
					return LoadState.Generating;
				}
				if (levelHasEnemies && !EnemyReadyActors.Contains(actor))
				{
					return LoadState.Generating;
				}
			}
			return LoadState.Loaded;
		}

		private static bool IsBlocking(LoadState s)
		{
			if (!reloadScenePresent && !outroInFlight)
			{
				return s != LoadState.Ready;
			}
			return s == LoadState.Loading;
		}

		private static Color StateColor(LoadState s, bool stuckBlocker)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (stuckBlocker)
			{
				return LoadingWidgetStyle.NativeAccent;
			}
			return (Color)(s switch
			{
				LoadState.Ready => Color.white, 
				LoadState.Loaded => new Color(0.78f, 0.8f, 0.82f), 
				LoadState.Generating => LoadingWidgetStyle.StateGenerating, 
				_ => LoadingWidgetStyle.NativeAccent, 
			});
		}

		private static string StateLabel(LoadState s)
		{
			return s switch
			{
				LoadState.Ready => "READY", 
				LoadState.Loaded => "LOADED", 
				LoadState.Generating => "BUILDING", 
				_ => "LOADING", 
			};
		}

		private static string NameOf(PlayerAvatar? avatar, Player p)
		{
			if ((Object)(object)avatar != (Object)null)
			{
				try
				{
					return AvatarName(avatar);
				}
				catch
				{
				}
			}
			return p.NickName;
		}

		private void LogDiagnostics(Player[] players)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.StateDiagnostics == null || !Plugin.StateDiagnostics.Value || Time.unscaledTime < nextDiagTime)
			{
				return;
			}
			nextDiagTime = Time.unscaledTime + 2f;
			try
			{
				Scene activeScene = SceneManager.GetActiveScene();
				string name = ((Scene)(ref activeScene)).name;
				Plugin.Logger.LogInfo((object)($"[LoadPanel diag] scene={name} gap={inReloadGap} reloadPresent={reloadScenePresent} outro={outroInFlight} " + $"stuck={loadStuck}(game={gameStuck}) lgPresent={levelGeneratorPresent} generated={levelGenerated} hasEnemies={levelHasEnemies} " + "sceneLoaded=[" + string.Join(",", SceneLoadedActors) + "] spawnedReady=[" + string.Join(",", SpawnedReadyActors) + "] enemyReady=[" + string.Join(",", EnemyReadyActors) + "] reloadReady=[" + string.Join(",", ReloadReadyActors) + "] " + $"queued={Bridge.PendingLobbyReturn}"));
				foreach (Player val in players)
				{
					ActorAvatars.TryGetValue(val.ActorNumber, out PlayerAvatar value);
					string arg = "n/a";
					if ((Object)(object)value != (Object)null)
					{
						try
						{
							arg = AvatarOutroDone(value).ToString();
						}
						catch
						{
							arg = "err";
						}
					}
					Plugin.Logger.LogInfo((object)($"[LoadPanel diag]   actor={val.ActorNumber} name={Bridge.SanitizeName(val.NickName)} " + $"avatar={(Object)(object)value != (Object)null} outroDone={arg} state={StateOf(val.ActorNumber)}"));
				}
			}
			catch
			{
			}
		}

		private static void BuildLoadSnapshot()
		{
			if (windowOpenSince < 0f)
			{
				windowOpenSince = Time.unscaledTime;
			}
			SceneLoadedActors.Clear();
			SpawnedReadyActors.Clear();
			EnemyReadyActors.Clear();
			ReloadReadyActors.Clear();
			try
			{
				SnapshotSceneLoaded();
			}
			catch
			{
			}
			try
			{
				levelGeneratorPresent = SnapshotLevelProgress();
			}
			catch
			{
				levelGeneratorPresent = false;
				levelHasEnemies = false;
				levelGenerated = false;
			}
			try
			{
				gameStuck = LoadingStuckRaw();
			}
			catch
			{
				gameStuck = false;
			}
			bool flag = Time.unscaledTime - windowOpenSince >= 35f;
			loadStuck = gameStuck || flag;
			outroInFlight = OutroNow();
			reloadScenePresent = false;
			if (inReloadGap)
			{
				try
				{
					reloadScenePresent = SnapshotReloadReady();
				}
				catch
				{
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ResolveOutroEnumRaw()
		{
			outroEndValue = Convert.ToInt32(Enum.Parse(typeof(gameState), "End"));
			outroEndWaitValue = Convert.ToInt32(Enum.Parse(typeof(gameState), "EndWait"));
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool OutroInFlightRaw()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			GameDirector val = GameDirector.instance;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			int num = (int)val.currentState;
			if (num != outroEndValue)
			{
				return num == outroEndWaitValue;
			}
			return true;
		}

		private static void EnsureOutroEnum()
		{
			if (outroEnumResolved)
			{
				return;
			}
			outroEnumResolved = true;
			try
			{
				ResolveOutroEnumRaw();
				outroTierAlive = true;
			}
			catch
			{
				outroTierAlive = false;
			}
		}

		private static bool OutroNow()
		{
			EnsureOutroEnum();
			if (!outroTierAlive)
			{
				return false;
			}
			try
			{
				return OutroInFlightRaw();
			}
			catch
			{
				return false;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool SnapshotReloadReady()
		{
			ReloadScene val = reloadSceneCache;
			if ((Object)(object)val == (Object)null)
			{
				if (Time.unscaledTime < nextReloadSearchTime)
				{
					return false;
				}
				val = (reloadSceneCache = Object.FindObjectOfType<ReloadScene>());
				if ((Object)(object)val == (Object)null)
				{
					nextReloadSearchTime = Time.unscaledTime + 0.25f;
					return false;
				}
			}
			if (val.PlayersReadyList == null)
			{
				return false;
			}
			foreach (Player playersReady in val.PlayersReadyList)
			{
				if (playersReady != null)
				{
					ReloadReadyActors.Add(playersReady.ActorNumber);
				}
			}
			return true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool AvatarOutroDone(PlayerAvatar a)
		{
			return a.outroDone;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void SnapshotSceneLoaded()
		{
			NetworkManager val = NetworkManager.instance;
			if ((Object)(object)val == (Object)null || val.instantiatedPlayerAvatarsList == null)
			{
				return;
			}
			foreach (Player instantiatedPlayerAvatars in val.instantiatedPlayerAvatarsList)
			{
				if (instantiatedPlayerAvatars != null)
				{
					SceneLoadedActors.Add(instantiatedPlayerAvatars.ActorNumber);
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool SnapshotLevelProgress()
		{
			LevelGenerator val = LevelGenerator.Instance;
			if ((Object)(object)val == (Object)null)
			{
				levelHasEnemies = false;
				levelGenerated = false;
				return false;
			}
			levelGenerated = val.Generated;
			levelHasEnemies = (Object)(object)val.Level != (Object)null && val.Level.HasEnemies;
			if (val.SpawnedReadyPlayerList != null)
			{
				foreach (Player spawnedReadyPlayer in val.SpawnedReadyPlayerList)
				{
					if (spawnedReadyPlayer != null)
					{
						SpawnedReadyActors.Add(spawnedReadyPlayer.ActorNumber);
					}
				}
			}
			if (val.EnemyReadyPlayerList != null)
			{
				foreach (Player enemyReadyPlayer in val.EnemyReadyPlayerList)
				{
					if (enemyReadyPlayer != null)
					{
						EnemyReadyActors.Add(enemyReadyPlayer.ActorNumber);
					}
				}
			}
			return true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool AvatarReady(PlayerAvatar a)
		{
			return a.levelAnimationCompleted;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static string AvatarName(PlayerAvatar a)
		{
			return a.playerName;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void BuildActorAvatarMap()
		{
			GameDirector val = GameDirector.instance;
			if ((Object)(object)val == (Object)null || val.PlayerList == null)
			{
				return;
			}
			foreach (PlayerAvatar player in val.PlayerList)
			{
				if (!((Object)(object)player == (Object)null))
				{
					PhotonView photonView = player.photonView;
					if ((Object)(object)photonView != (Object)null && photonView.Owner != null)
					{
						ActorAvatars[photonView.Owner.ActorNumber] = player;
					}
				}
			}
		}

		private static bool IsLevelLoading()
		{
			try
			{
				if (!PhotonNetwork.InRoom)
				{
					ResetWindow();
					return false;
				}
				int num;
				try
				{
					num = LoadingScreenStateRaw();
				}
				catch
				{
					ResetWindow();
					return false;
				}
				bool flag;
				try
				{
					flag = RunIsLobbyMenuRaw();
				}
				catch
				{
					flag = false;
				}
				bool flag2;
				try
				{
					flag2 = MenuLevelRaw() && !flag;
				}
				catch
				{
					flag2 = false;
				}
				if (flag2)
				{
					ResetWindow();
					return false;
				}
				if (num == 1)
				{
					if (flag && !windowOpen && !OutroNow())
					{
						return false;
					}
					inReloadGap = false;
					windowOpen = true;
					return true;
				}
				if (!windowOpen)
				{
					return false;
				}
				if (num == -1)
				{
					if (PhotonNetwork.InRoom)
					{
						inReloadGap = true;
						return true;
					}
					ResetWindow();
					return false;
				}
				ResetWindow();
				return false;
			}
			catch
			{
				return false;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool LoadingStuckRaw()
		{
			LoadingUI val = LoadingUI.instance;
			if ((Object)(object)val != (Object)null)
			{
				return val.stuckActive;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static int LoadingScreenStateRaw()
		{
			LoadingUI val = LoadingUI.instance;
			if ((Object)(object)val == (Object)null)
			{
				return -1;
			}
			return ((Component)val).gameObject.activeInHierarchy ? 1 : 0;
		}

		internal static void ResetSession()
		{
			ResetWindow();
		}

		private static void ResetWindow()
		{
			windowOpen = false;
			windowOpenSince = -1f;
			inReloadGap = false;
			reloadSceneCache = null;
			nextReloadSearchTime = 0f;
			lobbyArmedUntil = 0f;
			Loudness.Clear();
			expandedActor = -1;
			sliderDragActor = -1;
			lastHeaderLoaded = -1;
			lastHeaderTotal = -1;
			lastHeaderStuck = false;
			gameStuck = false;
			loadStuck = false;
		}

		private void OnDestroy()
		{
			Loudness.Clear();
		}
	}
	internal static class LoadingWidgetStyle
	{
		internal static readonly Color RoleHost = Hex(16765514);

		internal static readonly Color RoleModerator = Hex(6730495);

		internal static readonly Color RoleModUser = Hex(10211706);

		internal static readonly Color RoleNone = Hex(9085104);

		internal const string DimTimeHex = "#9aa4ad";

		internal const string NativeAccentHex = "#FF8500";

		internal const string DangerTextHex = "#F0736B";

		internal static readonly Color StateGenerating = new Color(0.98f, 0.82f, 0.25f);

		internal static readonly Color BarTrack = new Color(1f, 1f, 1f, 0.1f);

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

		internal static readonly Color DangerTextHover = new Color(1f, 0.62f, 0.58f);

		internal static readonly Color NativeBtnIdle = Color.gray;

		internal static readonly Color NativeBtnHover = Color.white;

		internal static readonly Color NativeBtnClick = new Color(1f, 0.55f, 0f);

		internal static readonly Color NativeHoverFill = new Color(0.08f, 0.2f, 0.4f, 0.75f);

		internal static readonly Color NativeAccent = new Color(1f, 0.522f, 0f);

		internal static Color GetVolumeColor(float volume)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_001c: 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 (!(volume < 0.5f))
			{
				return Color.Lerp(Color.yellow, new Color(1f, 0.3f, 0.3f), (volume - 0.5f) * 2f);
			}
			return Color.Lerp(new Color(0.3f, 1f, 0.3f), Color.yellow, volume * 2f);
		}

		private static Color Hex(int rgb)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			return new Color((float)((rgb >> 16) & 0xFF) / 255f, (float)((rgb >> 8) & 0xFF) / 255f, (float)(rgb & 0xFF) / 255f);
		}
	}
	[BepInPlugin("RED.LoadingWidget", "LoadingWidget", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony? harmony;

		internal static ManualLogSource Logger { get; private set; }

		internal static ConfigEntry<bool>? StateDiagnostics { get; private set; }

		private void Awake()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			StateDiagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "StateDiagnostics", false, "Log the [LoadPanel diag] per-player load-state signals every 2s while the panel is visible (for diagnosing wrong LOADING/BUILDING/LOADED/READY states in the field).");
			bool standalone;
			IPanelBackend panelBackend = ResolveBackend(out standalone);
			if (panelBackend == null)
			{
				return;
			}
			Bridge.Select(panelBackend);
			LoadingPanel.Init();
			harmony = new Harmony("RED.LoadingWidget");
			try
			{
				harmony.PatchAll(typeof(DisconnectReset));
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("DisconnectReset patch failed (game update?): " + ex.Message + " - session reset on disconnect disabled, panel unaffected."));
			}
			if (standalone)
			{
				try
				{
					harmony.PatchAll(typeof(StandaloneVoice));
				}
				catch (Exception ex2)
				{
					Logger.LogWarning((object)("Voice plumbing unavailable (" + ex2.GetType().Name + ") - talking bars and volume disabled"));
				}
			}
			Logger.LogInfo((object)("RED.LoadingWidget v1.1.0 has loaded (" + (standalone ? "standalone" : "SharePermissions bridge") + " mode)!"));
		}

		private IPanelBackend? ResolveBackend(out bool standalone)
		{
			standalone = false;
			if (Chainloader.PluginInfos.TryGetValue("RED.SharePermissions", out var value))
			{
				Version version = value.Metadata.Version;
				if (version < new Version("1.17.0"))
				{
					Logger.LogInfo((object)($"SharePermissions {version} found, but its loading panel moved here only in " + "1.17.0 - staying dormant so the panel is not drawn twice. Update SharePermissions (or uninstall it) to activate LoadingWidget."));
					return null;
				}
				try
				{
					SharePermissionsBackend result = SharePermissionsBackend.Create();
					Logger.LogInfo((object)$"SharePermissions {version} detected - full integration active");
					return result;
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)($"SharePermissions {version} is installed but its LoadingWidgetBridge failed to load " + "(" + ex.GetType().Name + ") - falling back to standalone mode"));
				}
			}
			standalone = true;
			ConfigEntry<bool> showLoadingPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowLoadingPanel", true, "Show the loading-screen panel during multiplayer level loads (every player running the mod sees it; moderation actions are host-only in standalone mode). When SharePermissions v1.17.0+ is installed, its own UI / ShowLoadingPanel setting governs instead and this entry is ignored.");
			return new StandaloneBackend(showLoadingPanel);
		}

		private void OnDestroy()
		{
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	internal static class PluginInfo
	{
		internal const string Guid = "RED.LoadingWidget";

		internal const string Name = "LoadingWidget";

		internal const string Version = "1.1.0";

		internal const string SharePermissionsGuid = "RED.SharePermissions";

		internal const string SharePermissionsMinVersion = "1.17.0";
	}
	internal sealed class SharePermissionsBackend : IPanelBackend
	{
		public bool ShowLoadingPanel => LoadingWidgetBridge.ShowLoadingPanel;

		public bool LocalCanModerate => LoadingWidgetBridge.LocalCanModerate;

		public bool PendingLobbyReturn => LoadingWidgetBridge.PendingLobbyReturn;

		public bool IsMasterOrSingleplayer => LoadingWidgetBridge.IsMasterOrSingleplayer;

		public float VolumeMax => LoadingWidgetBridge.VolumeMax;

		private SharePermissionsBackend()
		{
		}

		internal static SharePermissionsBackend Create()
		{
			ProbeBridgeRaw();
			return new SharePermissionsBackend();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ProbeBridgeRaw()
		{
			_ = LoadingWidgetBridge.VolumeMax;
		}

		public int RoleTier(Player? player)
		{
			return LoadingWidgetBridge.RoleTier(player);
		}

		public float VoiceAmplitude(int actorNumber)
		{
			return LoadingWidgetBridge.VoiceAmplitude(actorNumber);
		}

		public float VolumeFactor(int actorNumber)
		{
			return LoadingWidgetBridge.VolumeFactor(actorNumber);
		}

		public void SetVolume(int actorNumber, float factor)
		{
			LoadingWidgetBridge.SetVolume(actorNumber, factor);
		}

		public string SanitizeName(string? name, string? fallback = "Unknown")
		{
			return LoadingWidgetBridge.SanitizeName(name, fallback);
		}

		public bool CanKick(PlayerAvatar target)
		{
			return LoadingWidgetBridge.CanKick(target);
		}

		public bool CanKickActor(Player target)
		{
			return LoadingWidgetBridge.CanKickActor(target);
		}

		public void Kick(PlayerAvatar target, bool ban)
		{
			LoadingWidgetBridge.Kick(target, ban);
		}

		public void KickGhost(Player ghost, bool ban)
		{
			LoadingWidgetBridge.KickGhost(ghost, ban);
		}

		public void BackToLobby()
		{
			LoadingWidgetBridge.BackToLobby();
		}

		public void ForceLobbyReload()
		{
			StandaloneLobby.ForceLobbyReload();
		}

		public void Tick()
		{
		}

		public void ResetSession()
		{
		}
	}
	internal sealed class StandaloneBackend : IPanelBackend
	{
		private readonly ConfigEntry<bool> showLoadingPanel;

		public bool ShowLoadingPanel => showLoadingPanel.Value;

		public bool LocalCanModerate
		{
			get
			{
				try
				{
					return IsMasterClientRaw();
				}
				catch
				{
					return false;
				}
			}
		}

		public bool PendingLobbyReturn => StandaloneLobby.PendingLobbyReturn;

		public bool IsMasterOrSingleplayer
		{
			get
			{
				try
				{
					return IsMasterOrSingleplayerRaw();
				}
				catch
				{
					return false;
				}
			}
		}

		public float VolumeMax => 2f;

		internal StandaloneBackend(ConfigEntry<bool> showLoadingPanel)
		{
			this.showLoadingPanel = showLoadingPanel;
		}

		public int RoleTier(Player? player)
		{
			if (player == null || !player.IsMasterClient)
			{
				return 0;
			}
			return 3;
		}

		public float VoiceAmplitude(int actorNumber)
		{
			return StandaloneVoice.AmplitudeFor(actorNumber);
		}

		public float VolumeFactor(int actorNumber)
		{
			return StandaloneVoice.FactorFor(actorNumber);
		}

		public void SetVolume(int actorNumber, float factor)
		{
			StandaloneVoice.SetFactor(actorNumber, factor);
		}

		public string SanitizeName(string? name, string? fallback = "Unknown")
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return fallback ?? "";
			}
			string text = Regex.Replace(name, "<[^>]*>", string.Empty);
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			string text2 = text;
			foreach (char c in text2)
			{
				if (!char.IsControl(c))
				{
					stringBuilder.Append(c);
				}
			}
			string text3 = stringBuilder.ToString().Trim();
			if (string.IsNullOrWhiteSpace(text3))
			{
				return fallback ?? "";
			}
			if (text3.Length > 32)
			{
				text3 = text3.Substring(0, 32) + "...";
			}
			return text3;
		}

		public bool CanKick(PlayerAvatar target)
		{
			if ((Object)(object)target == (Object)null || !LocalCanModerate)
			{
				return false;
			}
			try
			{
				return !AvatarIsLocalRaw(target);
			}
			catch
			{
				return false;
			}
		}

		public bool CanKickActor(Player target)
		{
			if (target != null && !target.IsLocal && !target.IsMasterClient)
			{
				return LocalCanModerate;
			}
			return false;
		}

		public void Kick(PlayerAvatar target, bool ban)
		{
			if (!CanKick(target))
			{
				return;
			}
			try
			{
				KickAvatarRaw(target, ban);
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Kick failed (" + ex.GetType().Name + ")"));
			}
		}

		public void KickGhost(Player ghost, bool ban)
		{
			if (!CanKickActor(ghost))
			{
				return;
			}
			try
			{
				KickByActorRaw(ghost, ban);
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Ghost kick failed (" + ex.GetType().Name + ")"));
			}
		}

		public void BackToLobby()
		{
			StandaloneLobby.ReturnToLobby();
		}

		public void ForceLobbyReload()
		{
			StandaloneLobby.ForceLobbyReload();
		}

		public void Tick()
		{
			StandaloneLobby.Tick();
		}

		public void ResetSession()
		{
			StandaloneVoice.Clear();
			StandaloneLobby.Reset();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool IsMasterClientRaw()
		{
			return SemiFunc.IsMasterClient();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool IsMasterOrSingleplayerRaw()
		{
			return SemiFunc.IsMasterClientOrSingleplayer();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool AvatarIsLocalRaw(PlayerAvatar avatar)
		{
			return avatar.isLocal;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void KickAvatarRaw(PlayerAvatar target, bool ban)
		{
			NetworkManager instance = NetworkManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (ban)
				{
					instance.BanPlayer(target);
				}
				else
				{
					instance.KickPlayer(target);
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void KickByActorRaw(Player ghost, bool ban)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			object[] array = new object[1] { ghost.ActorNumber };
			RaiseEventOptions val = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)1
			};
			PhotonNetwork.RaiseEvent((byte)(ban ? 124u : 123u), (object)array, val, SendOptions.SendReliable);
			try
			{
				if (PhotonNetwork.IsMasterClient)
				{
					PhotonNetwork.CloseConnection(ghost);
				}
			}
			catch
			{
			}
		}
	}
	internal static class StandaloneLobby
	{
		internal static bool PendingLobbyReturn;

		internal static void ReturnToLobby()
		{
			try
			{
				ReturnToLobbyRaw();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("BackToLobby failed (" + ex.GetType().Name + ")"));
			}
		}

		internal static void ForceLobbyReload()
		{
			try
			{
				ForceLobbyReloadRaw();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("ForceLobbyReload failed (" + ex.GetType().Name + ")"));
			}
		}

		internal static void Tick()
		{
			if (!PendingLobbyReturn)
			{
				return;
			}
			try
			{
				TickRaw();
			}
			catch
			{
				PendingLobbyReturn = false;
			}
		}

		internal static void Reset()
		{
			PendingLobbyReturn = false;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ReturnToLobbyRaw()
		{
			if (SemiFunc.MenuLevel())
			{
				Plugin.Logger.LogWarning((object)"BackToLobby ignored - not in a run");
				return;
			}
			RunManager instance = RunManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (!instance.restarting)
			{
				ChangeLevelToLobbyRaw(instance);
				return;
			}
			if (!instance.restartingDone)
			{
				try
				{
					if (RetargetInFlightToLobbyRaw(instance))
					{
						return;
					}
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("BackToLobby retarget failed (" + ex.GetType().Name + ") - queuing instead"));
				}
			}
			PendingLobbyReturn = true;
			Plugin.Logger.LogInfo((object)"BackToLobby queued - will run once the in-flight load completes");
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void TickRaw()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Invalid comparison between Unknown and I4
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				PendingLobbyReturn = false;
				return;
			}
			RunManager instance = RunManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (SemiFunc.RunIsLobbyMenu() || SemiFunc.MenuLevel())
			{
				PendingLobbyReturn = false;
			}
			else if (!instance.restarting)
			{
				GameDirector instance2 = GameDirector.instance;
				if (!((Object)(object)instance2 == (Object)null) && (int)instance2.currentState == 2)
				{
					PendingLobbyReturn = false;
					Plugin.Logger.LogInfo((object)"BackToLobby: running queued lobby return");
					ReturnToLobbyRaw();
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ChangeLevelToLobbyRaw(RunManager rm)
		{
			int num = (SemiFunc.IsLevelShop(rm.levelCurrent) ? 1 : (SemiFunc.RunIsLobby() ? 2 : 0));
			rm.ChangeLevel(true, SemiFunc.RunIsArena(), (ChangeLevelType)3);
			SemiFunc.StatSetSaveLevel(num);
			rm.loadLevel = num;
			StatsManager.instance.SaveFileSave();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool RetargetInFlightToLobbyRaw(RunManager rm)
		{
			if (!TrySyncLobbyDestinationRaw(rm))
			{
				return false;
			}
			int saveLevel = rm.saveLevel;
			SemiFunc.StatSetSaveLevel(saveLevel);
			rm.loadLevel = saveLevel;
			StatsManager.instance.SaveFileSave();
			PendingLobbyReturn = true;
			Plugin.Logger.LogInfo((object)"BackToLobby: retargeted the in-flight load to the lobby menu");
			return true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool TrySyncLobbyDestinationRaw(RunManager rm)
		{
			if ((Object)(object)rm.levelCurrent == (Object)(object)rm.levelLobbyMenu)
			{
				return true;
			}
			if (!GameManager.Multiplayer())
			{
				rm.levelCurrent = rm.levelLobbyMenu;
				return true;
			}
			RunManagerPUN runManagerPUN = rm.runManagerPUN;
			if ((Object)(object)runManagerPUN == (Object)null || (Object)(object)runManagerPUN.photonView == (Object)null)
			{
				return false;
			}
			runManagerPUN.photonView.RPC("UpdateLevelRPC", (RpcTarget)4, new object[3]
			{
				((Object)rm.levelLobbyMenu).name,
				rm.levelsCompleted,
				false
			});
			rm.levelCurrent = rm.levelLobbyMenu;
			return true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ForceLobbyReloadRaw()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			RunManager instance = RunManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			bool flag = false;
			try
			{
				flag = TrySyncLobbyDestinationRaw(instance);
			}
			catch
			{
			}
			instance.waitToChangeScene = false;
			instance.lobbyJoin = false;
			instance.restarting = false;
			instance.restartingDone = false;
			instance.gameOver = false;
			instance.allPlayersDead = false;
			instance.allPlayersDeadCheckDisabled = true;
			try
			{
				StatsManager instance2 = StatsManager.instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					instance2.SaveFileSave();
				}
			}
			catch
			{
			}
			try
			{
				NetworkManager instance3 = NetworkManager.instance;
				if ((Object)(object)instance3 != (Object)null)
				{
					instance3.DestroyAll();
				}
			}
			catch
			{
			}
			PendingLobbyReturn = true;
			Scene activeScene = SceneManager.GetActiveScene();
			string text = ((((Scene)(ref activeScene)).name == "Reload") ? "Main" : "Reload");
			if (GameManager.Multiplayer() && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.AutomaticallySyncScene = true;
				PhotonNetwork.LoadLevel(text);
			}
			else
			{
				SceneManager.LoadSceneAsync(text);
			}
			Plugin.Logger.LogInfo((object)$"ForceLobbyReload: wedged transition pipeline restarted room-wide (forced scene: {text}, lobby synced: {flag})");
		}
	}
	[HarmonyPatch(typeof(PlayerVoiceChat), "Update")]
	internal static class StandaloneVoice
	{
		internal const float VolumeMin = 0f;

		internal const float VolumeMax = 2f;

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

		private static readonly Dictionary<int, float> FactorByActor = new Dictionary<int, float>();

		private static readonly float[] SampleBuf = new float[1024];

		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Update_Postfix(PlayerVoiceChat __instance)
		{
			PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
			if (!((Object)(object)component == (Object)null) && component.Owner != null)
			{
				int actorNumber = component.Owner.ActorNumber;
				ByActor[actorNumber] = __instance;
				float num = FactorFor(actorNumber);
				if (num != 1f)
				{
					ApplyVolumeFactor(__instance, num);
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void ApplyVolumeFactor(PlayerVoiceChat pvc, float factor)
		{
			if ((Object)(object)pvc.lowPassLogic != (Object)null)
			{
				AudioLowPassLogic lowPassLogic = pvc.lowPassLogic;
				lowPassLogic.Volume *= factor;
			}
			if ((Object)(object)pvc.lowPassLogicTTS != (Object)null && (Object)(object)pvc.playerAvatar != (Object)null)
			{
				AudioLowPassLogic lowPassLogicTTS = pvc.lowPassLogicTTS;
				lowPassLogicTTS.Volume *= factor;
			}
		}

		internal static float FactorFor(int actorNumber)
		{
			if (!FactorByActor.TryGetValue(actorNumber, out var value))
			{
				return 1f;
			}
			return value;
		}

		internal static void SetFactor(int actorNumber, float factor)
		{
			float num = Mathf.Clamp(factor, 0f, 2f);
			if (num == 1f)
			{
				FactorByActor.Remove(actorNumber);
			}
			else
			{
				FactorByActor[actorNumber] = num;
			}
		}

		internal static float AmplitudeFor(int actorNumber)
		{
			if (!ByActor.TryGetValue(actorNumber, out PlayerVoiceChat value) || (Object)(object)value == (Object)null)
			{
				return 0f;
			}
			try
			{
				AudioSource audioSource = value.audioSource;
				if ((Object)(object)audioSource == (Object)null || (Object)(object)audioSource.clip == (Object)null || !audioSource.isPlaying)
				{
					return 0f;
				}
				audioSource.clip.GetData(SampleBuf, audioSource.timeSamples);
				float num = 0f;
				for (int i = 0; i < SampleBuf.Length; i++)
				{
					num += Mathf.Abs(SampleBuf[i]);
				}
				return num / (float)SampleBuf.Length;
			}
			catch
			{
				return 0f;
			}
		}

		internal static void Clear()
		{
			ByActor.Clear();
			FactorByActor.Clear();
		}
	}
}