Decompiled source of SharePermissions v1.0.7

SharePermissions.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using MenuLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("RED")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+aaa6ba81a3622ca3cfb7a1081aceefda53783ded")]
[assembly: AssemblyProduct("SharePermissions")]
[assembly: AssemblyTitle("SharePermissions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 SharePermissions
{
	internal class Events : IOnEventCallback
	{
		internal bool registered = false;

		internal string clientRandomString = string.Empty;

		private static Random random = new Random();

		internal const byte EventCode = 184;

		internal static Events instance { get; private set; } = null;


		public Events()
		{
			instance = this;
			if (!registered)
			{
				PhotonNetwork.AddCallbackTarget((object)this);
				registered = true;
			}
		}

		public static void Init()
		{
			if (instance == null)
			{
				new Events();
			}
		}

		internal static void SendCommand(string command, string secret, string fromSteamId, object[] args, ReceiverGroup receiverGroup)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			SharePermissions.Logger.LogInfo((object)("Send command: " + command + "; to: " + ((object)(ReceiverGroup)(ref receiverGroup)).ToString()));
			object[] array = new object[3 + args.Length];
			array[0] = command;
			array[1] = ComputeSha256Hash(secret + fromSteamId);
			array[2] = fromSteamId;
			args.CopyTo(array, 3);
			PhotonNetwork.RaiseEvent((byte)184, (object)array, new RaiseEventOptions
			{
				Receivers = receiverGroup
			}, SendOptions.SendReliable);
		}

		private static string ComputeSha256Hash(string rawData)
		{
			using SHA256 sHA = SHA256.Create();
			byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(rawData));
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		public void OnEvent(EventData photonEvent)
		{
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code != 184)
			{
				return;
			}
			object[] array = (object[])photonEvent.CustomData;
			int sender = photonEvent.Sender;
			Room currentRoom = PhotonNetwork.CurrentRoom;
			Player val = ((currentRoom != null) ? currentRoom.GetPlayer(sender, false) : null);
			string text = null;
			bool flag = val != null && val.IsMasterClient;
			if (val != null)
			{
				foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
				{
					PhotonView val2 = ((item != null) ? ((Component)item).GetComponent<PhotonView>() : null);
					if ((Object)(object)val2 != (Object)null && val2.Owner != null && val2.Owner.ActorNumber == sender)
					{
						text = SemiFunc.PlayerGetSteamID(item);
						break;
					}
				}
			}
			string text2 = array[0].ToString();
			if (!SemiFunc.IsMasterClient())
			{
				if (text2 == "InitModeratorAck" && flag)
				{
					string steamId = array[3].ToString();
					Moderators.Instance.AddModerator(steamId);
				}
			}
			else
			{
				if (array.Length < 3)
				{
					return;
				}
				string value = array[1].ToString();
				string nickName = val.NickName;
				string text3 = ComputeSha256Hash(SharePermissions.SecretCode.Value + text);
				if (text == null)
				{
					return;
				}
				SteamId val3 = default(SteamId);
				if (ulong.TryParse(text, out var result))
				{
					SteamId val4 = default(SteamId);
					val4.Value = result;
					val3 = val4;
				}
				if (!((SteamId)(ref val3)).IsValid)
				{
					SharePermissions.Logger.LogWarning((object)("Invalid SteamID received in event from: " + nickName + " (" + text + ")"));
					return;
				}
				if (SharePermissions.SecretCode == null || !text3.Equals(value))
				{
					SharePermissions.Logger.LogWarning((object)("Secret code is not equal, from: " + nickName + " (" + text + "); (your secret: " + text3 + ")"));
					return;
				}
				switch (text2)
				{
				case "KickPlayer":
				{
					string text7 = array[3].ToString();
					string text8 = array[4].ToString();
					PlayerAvatar val6 = SemiFunc.PlayerGetFromSteamID(text7);
					PhotonView val7 = ((val6 != null) ? ((Component)val6).GetComponent<PhotonView>() : null);
					bool flag2 = (Object)(object)val7 != (Object)null && val7.Owner != null && val7.Owner.IsMasterClient;
					bool flag3 = Moderators.Instance.IsModerator(text7);
					if (!flag2 && !flag3)
					{
						SharePermissions.LogWrite("Banning request " + SemiFunc.PlayerGetName(val6) + " (" + text7 + ") from player:" + nickName + "(" + text + ")");
						SharePermissions.Logger.LogInfo((object)("Banning request " + SemiFunc.PlayerGetName(val6) + " (" + text7 + ") from player:" + nickName + "(" + text + ")"));
						if (text8 == "kick")
						{
							NetworkManager.instance.KickPlayer(val6);
						}
						else
						{
							NetworkManager.instance.BanPlayer(val6);
						}
					}
					else
					{
						SharePermissions.Logger.LogWarning((object)("Ignoring banning request for master client or moderator " + SemiFunc.PlayerGetName(val6) + " (" + text7 + ") from player:" + nickName + "(" + text + ")"));
					}
					break;
				}
				case "KickGhostPlayer":
				{
					string text4 = array[3].ToString();
					string text5 = array[4].ToString();
					if (int.TryParse(text4, out var result2))
					{
						Room currentRoom2 = PhotonNetwork.CurrentRoom;
						Player val5 = ((currentRoom2 != null) ? currentRoom2.GetPlayer(result2, false) : null);
						if (val5 != null)
						{
							if (val5.IsMasterClient)
							{
								SharePermissions.Logger.LogWarning((object)$"Ignoring ghost kick request for master client (ActorNumber: {result2}) from: {nickName}");
								break;
							}
							string text6 = PlayerSteamIdCache.Instance.GetSteamId(result2) ?? val5.UserId;
							if (!string.IsNullOrEmpty(text6) && Moderators.Instance.IsModerator(text6))
							{
								SharePermissions.Logger.LogWarning((object)$"Ignoring ghost kick request for moderator (ActorNumber: {result2}, SteamID: {text6}) from: {nickName}");
								break;
							}
							PhotonNetwork.CloseConnection(val5);
							SharePermissions.LogWrite(string.Format("Ghost player kicked (ActorNumber: {0}, Name: {1}, SteamID: {2}) by: {3} ({4})", result2, val5.NickName, text6 ?? "unknown", nickName, text));
							SharePermissions.Logger.LogInfo((object)string.Format("Ghost player connection closed: {0} (ActorNumber: {1}, SteamID: {2})", val5.NickName, result2, text6 ?? "unknown"));
						}
						else
						{
							SharePermissions.Logger.LogWarning((object)$"Ghost player with ActorNumber {result2} not found");
						}
					}
					else
					{
						SharePermissions.Logger.LogWarning((object)("Invalid ActorNumber received for KickGhostPlayer: " + text4));
					}
					break;
				}
				case "InitModerator":
					SharePermissions.Logger.LogInfo((object)("Network event: InitModerator command received for steamId: " + text));
					Moderators.Instance.AddModerator(text);
					SendCommand("InitModeratorAck", "", SemiFunc.PlayerGetSteamID(PlayerAvatar.instance), new object[1] { text }, (ReceiverGroup)0);
					break;
				case "StartGame":
					SharePermissions.Logger.LogInfo((object)"Network event: StartGame command received.");
					SharePermissions.LogWrite("Start game request from player:" + nickName + "(" + text + ")");
					SharePermissions.StartGameClick();
					break;
				case "BackToLobby":
					SharePermissions.Logger.LogInfo((object)"Network event: BackToLobby command received.");
					SharePermissions.LogWrite("Return to lobby request from player:" + nickName + "(" + text + ")");
					SharePermissions.ReturnLobbyClick();
					break;
				default:
					SharePermissions.Logger.LogInfo((object)("Network event: Unknown command(" + array.Length + "): " + text2));
					break;
				}
			}
		}
	}
	internal class Menu
	{
		private struct PlayerValidationResult
		{
			public bool IsValid;

			public bool IsSpoofed;

			public string Reason;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static BuilderDelegate <>9__3_0;

			public static BuilderDelegate <>9__3_1;

			public static ShouldCloseMenuDelegate <>9__13_0;

			public static Func<PlayerAvatar, bool> <>9__13_1;

			internal void <Init>b__3_0(Transform parent)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				REPOButton val = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(306f, 12f));
				((TMP_Text)val.labelTMP).fontSize = 18f;
			}

			internal void <Init>b__3_1(Transform parent)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				REPOButton val = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(166f, 86f));
				((TMP_Text)val.labelTMP).fontSize = 18f;
			}

			internal bool <openPlayerListMenu>b__13_0()
			{
				return false;
			}

			internal bool <openPlayerListMenu>b__13_1(PlayerAvatar pa)
			{
				return (Object)(object)pa != (Object)null;
			}
		}

		[CompilerGenerated]
		private sealed class <openPageInternal>d__21 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public REPOPopupPage page;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <openPageInternal>d__21(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.05f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					page.OpenPage(false);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static bool menuOpened;

		private static REPOPopupPage kickPage;

		private static MenuButtonPopUp menuButtonPopup;

		public static void Init()
		{
			//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_0020: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			object obj = <>c.<>9__3_0;
			if (obj == null)
			{
				BuilderDelegate val = delegate(Transform parent)
				{
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					REPOButton val4 = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(306f, 12f));
					((TMP_Text)val4.labelTMP).fontSize = 18f;
				};
				<>c.<>9__3_0 = val;
				obj = (object)val;
			}
			MenuAPI.AddElementToLobbyMenu((BuilderDelegate)obj);
			object obj2 = <>c.<>9__3_1;
			if (obj2 == null)
			{
				BuilderDelegate val2 = delegate(Transform parent)
				{
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					REPOButton val3 = MenuAPI.CreateREPOButton("Mod", (Action)openPlayerListMenu, parent, new Vector2(166f, 86f));
					((TMP_Text)val3.labelTMP).fontSize = 18f;
				};
				<>c.<>9__3_1 = val2;
				obj2 = (object)val2;
			}
			MenuAPI.AddElementToEscapeMenu((BuilderDelegate)obj2);
			SharePermissions.Logger.LogInfo((object)"Inited!");
		}

		public static REPOPopupPage createMenu(string title)
		{
			REPOPopupPage val = MenuAPI.CreateREPOPopupPage(title, (PresetSide)0, false, true, -5f);
			addCloseButton(val);
			return val;
		}

		public static void toggleMenu()
		{
			if (!menuOpened)
			{
				openPlayerListMenu();
			}
			else
			{
				closePage(kickPage);
			}
		}

		public static void addLabel(REPOPopupPage parent, string text)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			string text2 = text;
			parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				REPOLabel val = MenuAPI.CreateREPOLabel(text2, scrollView, default(Vector2));
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
		}

		public static void addButton(REPOPopupPage parent, string text, Action action)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			string text2 = text;
			Action action2 = action;
			parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0010: 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)
				REPOButton val = MenuAPI.CreateREPOButton(text2, action2, scrollView, default(Vector2));
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
		}

		public static void addKickButton(REPOPopupPage parent, string text, string text2, Action kickAction, Action banAction)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			string text3 = text;
			Action kickAction2 = kickAction;
			Action banAction2 = banAction;
			parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
				REPOButton val = MenuAPI.CreateREPOButton(text3, (Action)delegate
				{
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					createCustomPopupMenu("Choose punishment", new Color(1f, 0.553f, 0f), "Player " + text3, kickAction2, banAction2, "Kick", "Ban");
				}, scrollView, default(Vector2));
				if (text3.Length > 24)
				{
					Vector2 labelSize = val.GetLabelSize();
					labelSize.x = 250f;
					val.overrideButtonSize = labelSize;
					REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>();
					val2.maxCharacters = 24;
				}
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
		}

		public static void addPlayerActionButton(REPOPopupPage parent, string playerName, string steamId, Action kickAction, Action banAction, Action muteAction, Action unmuteAction)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			string playerName2 = playerName;
			string steamId2 = steamId;
			Action unmuteAction2 = unmuteAction;
			Action muteAction2 = muteAction;
			REPOPopupPage parent2 = parent;
			Action kickAction2 = kickAction;
			Action banAction2 = banAction;
			parent2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
				REPOButton val = MenuAPI.CreateREPOButton(playerName2, (Action)delegate
				{
					//IL_0054: Unknown result type (might be due to invalid IL or missing references)
					bool flag = MutedPlayers.Instance.IsMuted(steamId2);
					string muteButtonText = (flag ? "Unmute" : "Mute");
					Action onMuteClicked = (flag ? unmuteAction2 : muteAction2);
					closePage(parent2);
					createPlayerActionPopup("Player Actions", new Color(1f, 0.553f, 0f), "Player: " + playerName2, kickAction2, banAction2, onMuteClicked, muteButtonText);
				}, scrollView, default(Vector2));
				if (playerName2.Length > 24)
				{
					Vector2 labelSize = val.GetLabelSize();
					labelSize.x = 250f;
					val.overrideButtonSize = labelSize;
					REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>();
					val2.maxCharacters = 24;
				}
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
		}

		private static void createPlayerActionPopup(string title, Color headerColor, string message, Action onKickClicked, Action onBanClicked, Action onMuteClicked, string muteButtonText)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			string message2 = message;
			Action onKickClicked2 = onKickClicked;
			Action onBanClicked2 = onBanClicked;
			string muteButtonText2 = muteButtonText;
			Action onMuteClicked2 = onMuteClicked;
			REPOPopupPage popupPage = MenuAPI.CreateREPOPopupPage(title, (PresetSide)0, false, true, -5f);
			popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				REPOLabel val4 = MenuAPI.CreateREPOLabel(message2, scrollView, default(Vector2));
				return ((REPOElement)val4).rectTransform;
			}, 0f, 0f);
			popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0028: 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)
				REPOButton val3 = MenuAPI.CreateREPOButton("Kick", (Action)delegate
				{
					closePage(popupPage);
					onKickClicked2?.Invoke();
				}, scrollView, default(Vector2));
				return ((REPOElement)val3).rectTransform;
			}, 0f, 0f);
			popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0028: 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)
				REPOButton val2 = MenuAPI.CreateREPOButton("Ban", (Action)delegate
				{
					closePage(popupPage);
					onBanClicked2?.Invoke();
				}, scrollView, default(Vector2));
				return ((REPOElement)val2).rectTransform;
			}, 0f, 0f);
			popupPage.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0029: 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)
				REPOButton val = MenuAPI.CreateREPOButton(muteButtonText2, (Action)delegate
				{
					closePage(popupPage);
					onMuteClicked2?.Invoke();
				}, scrollView, default(Vector2));
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
			popupPage.AddElement((BuilderDelegate)delegate(Transform transform)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Cancel", (Action)delegate
				{
					closePage(popupPage);
				}, transform, new Vector2(270f, 20f));
			});
			openPage(popupPage);
		}

		public static void closePage(REPOPopupPage page)
		{
			menuOpened = false;
			page.ClosePage(true);
			MenuManager.instance.PageRemove(page.menuPage);
		}

		public static void addCloseButton(REPOPopupPage parent)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			REPOPopupPage parent2 = parent;
			parent2.AddElement((BuilderDelegate)delegate(Transform transform)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				MenuAPI.CreateREPOButton("Close", (Action)delegate
				{
					closePage(parent2);
				}, transform, new Vector2(270f, 20f));
			});
		}

		private static void openPlayerListMenu()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_05fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0608: Expected O, but got Unknown
			REPOPopupPage playersMenu = createMenu("Mod menu");
			PlayerAvatar instance = PlayerAvatar.instance;
			string fromSteamId = SemiFunc.PlayerGetSteamID(instance);
			string secret = SharePermissions.SecretCode.Value;
			REPOPopupPage obj = playersMenu;
			object obj2 = <>c.<>9__13_0;
			if (obj2 == null)
			{
				ShouldCloseMenuDelegate val = () => false;
				<>c.<>9__13_0 = val;
				obj2 = (object)val;
			}
			obj.onEscapePressed = (ShouldCloseMenuDelegate)obj2;
			kickPage = playersMenu;
			List<PlayerAvatar> list = (from pa in Object.FindObjectsOfType<PlayerAvatar>()
				where (Object)(object)pa != (Object)null
				select pa).ToList();
			List<PlayerAvatar> list2 = new List<PlayerAvatar>();
			List<PlayerAvatar> list3 = new List<PlayerAvatar>();
			HashSet<int> actorNumbersWithAvatars = new HashSet<int>();
			foreach (PlayerAvatar item in list)
			{
				PlayerValidationResult playerValidationResult = ValidateNetworkPlayer(item);
				if (playerValidationResult.IsValid)
				{
					list2.Add(item);
					PhotonView component = ((Component)item).GetComponent<PhotonView>();
					if (((component != null) ? component.Owner : null) != null)
					{
						actorNumbersWithAvatars.Add(component.Owner.ActorNumber);
					}
				}
				else if (playerValidationResult.IsSpoofed)
				{
					list3.Add(item);
				}
			}
			List<Player> list4 = PhotonNetwork.PlayerList.Where((Player p) => !actorNumbersWithAvatars.Contains(p.ActorNumber)).ToList();
			foreach (PlayerAvatar item2 in list2)
			{
				try
				{
					string playerSteamId = SemiFunc.PlayerGetSteamID(item2);
					if (string.IsNullOrEmpty(playerSteamId))
					{
						continue;
					}
					string playerDisplayName = Moderators.Instance.GetPlayerDisplayName(item2);
					if (playerSteamId == fromSteamId)
					{
						addLabel(playersMenu, playerDisplayName + " (You)");
						continue;
					}
					addPlayerActionButton(playersMenu, playerDisplayName, playerSteamId, delegate
					{
						Events.SendCommand("KickPlayer", secret, fromSteamId, new object[2] { playerSteamId, "kick" }, (ReceiverGroup)2);
						closePage(playersMenu);
					}, delegate
					{
						Events.SendCommand("KickPlayer", secret, fromSteamId, new object[2] { playerSteamId, "ban" }, (ReceiverGroup)2);
						closePage(playersMenu);
					}, delegate
					{
						MutedPlayers.Instance.MutePlayer(playerSteamId);
						closePage(playersMenu);
					}, delegate
					{
						MutedPlayers.Instance.UnmutePlayer(playerSteamId);
						closePage(playersMenu);
					});
				}
				catch (Exception ex)
				{
					SharePermissions.Logger.LogWarning((object)$"Failed to add player to the menu: {item2} - {ex.Message}");
				}
			}
			if (list4.Count > 0)
			{
				foreach (Player ghostPlayer in list4)
				{
					try
					{
						string text = ghostPlayer.NickName ?? $"Unknown_{ghostPlayer.ActorNumber}";
						int actorNumber = ghostPlayer.ActorNumber;
						string text2 = PlayerSteamIdCache.Instance.GetSteamId(actorNumber) ?? ghostPlayer.UserId;
						string steamNickname = GetSteamNickname(text2);
						if (!string.IsNullOrEmpty(steamNickname) && steamNickname != text)
						{
							text = text + " (" + steamNickname + ")";
						}
						string text3 = "<color=#FFAA00>[GHOST]</color> " + text;
						addGhostPlayerButton(playersMenu, text3, ghostPlayer, delegate
						{
							KickGhostPlayer(ghostPlayer, "kick");
							closePage(playersMenu);
						}, delegate
						{
							KickGhostPlayer(ghostPlayer, "ban");
							closePage(playersMenu);
						});
						SharePermissions.Logger.LogWarning((object)string.Format("Ghost player detected: {0} (ActorNumber: {1}, SteamID: {2}, SteamNick: {3})", text, actorNumber, text2 ?? "null", steamNickname ?? "null"));
					}
					catch (Exception ex2)
					{
						SharePermissions.Logger.LogWarning((object)("Failed to add ghost player to menu: " + ex2.Message));
					}
				}
			}
			if (list3.Count > 0)
			{
				foreach (PlayerAvatar spoofedPlayer in list3)
				{
					try
					{
						string text4 = ((Object)spoofedPlayer).name;
						string text5 = null;
						string text6 = null;
						try
						{
							text5 = SemiFunc.PlayerGetSteamID(spoofedPlayer);
							text4 = SemiFunc.PlayerGetName(spoofedPlayer) ?? text4;
							text6 = GetSteamNickname(text5);
						}
						catch
						{
						}
						string text7 = text4;
						if (!string.IsNullOrEmpty(text6) && text6 != text4)
						{
							text7 = text4 + " (" + text6 + ")";
						}
						string text8 = "<color=#FF6600>[SPOOF]</color> " + text7;
						addSpoofedPlayerButton(playersMenu, text8, spoofedPlayer, delegate
						{
							KickSpoofedPlayer(spoofedPlayer, "kick");
							closePage(playersMenu);
						}, delegate
						{
							KickSpoofedPlayer(spoofedPlayer, "ban");
							closePage(playersMenu);
						});
						SharePermissions.Logger.LogWarning((object)("Spoofed player added to menu: " + text4 + " (SteamID: " + (text5 ?? "null") + ", SteamNick: " + (text6 ?? "null") + ")"));
					}
					catch (Exception ex3)
					{
						SharePermissions.Logger.LogWarning((object)("Failed to add spoofed player to menu: " + ex3.Message));
					}
				}
			}
			playersMenu.AddElement((BuilderDelegate)delegate(Transform transform)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (SemiFunc.RunIsLobbyMenu())
				{
					MenuAPI.CreateREPOButton("Start game", (Action)delegate
					{
						//IL_0015: Unknown result type (might be due to invalid IL or missing references)
						MenuAPI.OpenPopup("Confirm", new Color(1f, 0.553f, 0f), "Start the game or maybe 5 minutes wait?", (Action)delegate
						{
							Events.SendCommand("StartGame", secret, fromSteamId, Array.Empty<object>(), (ReceiverGroup)2);
							closePage(playersMenu);
						}, (Action)null);
					}, transform, new Vector2(150f, 20f));
				}
				else
				{
					MenuAPI.CreateREPOButton("Back to lobby", (Action)delegate
					{
						//IL_0015: Unknown result type (might be due to invalid IL or missing references)
						MenuAPI.OpenPopup("Confirm", new Color(1f, 0.553f, 0f), "Back to the lobby?", (Action)delegate
						{
							Events.SendCommand("BackToLobby", secret, fromSteamId, Array.Empty<object>(), (ReceiverGroup)2);
							closePage(playersMenu);
						}, (Action)null);
					}, transform, new Vector2(150f, 20f));
				}
			});
			openPage(playersMenu);
		}

		public static void addSpoofedPlayerButton(REPOPopupPage parent, string text, PlayerAvatar spoofedPlayer, Action kickAction, Action banAction)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			string text2 = text;
			Action kickAction2 = kickAction;
			Action banAction2 = banAction;
			parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
				REPOButton val = MenuAPI.CreateREPOButton(text2, (Action)delegate
				{
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					createCustomPopupMenu("Suspicious Player", new Color(1f, 0.2f, 0f), "This player may be spoofed!\n" + text2, kickAction2, banAction2, "Kick", "Ban");
				}, scrollView, default(Vector2));
				if (text2.Length > 24)
				{
					Vector2 labelSize = val.GetLabelSize();
					labelSize.x = 250f;
					val.overrideButtonSize = labelSize;
					REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>();
					val2.maxCharacters = 24;
				}
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
		}

		private static void KickSpoofedPlayer(PlayerAvatar spoofedPlayer, string type)
		{
			try
			{
				string text = null;
				try
				{
					text = SemiFunc.PlayerGetSteamID(spoofedPlayer);
				}
				catch
				{
				}
				if (!string.IsNullOrEmpty(text))
				{
					string fromSteamId = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance);
					string value = SharePermissions.SecretCode.Value;
					Events.SendCommand("KickPlayer", value, fromSteamId, new object[2] { text, type }, (ReceiverGroup)2);
					SharePermissions.Logger.LogInfo((object)("Sent kick command for spoofed player via SteamID: " + text));
					return;
				}
				PhotonView component = ((Component)spoofedPlayer).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null && component.Owner != null && SemiFunc.IsMasterClient())
				{
					if (type == "kick")
					{
						NetworkManager.instance.KickPlayer(spoofedPlayer);
					}
					else
					{
						NetworkManager.instance.BanPlayer(spoofedPlayer);
					}
					SharePermissions.Logger.LogInfo((object)("Kicked spoofed player directly: " + ((Object)spoofedPlayer).name));
				}
				else if (SemiFunc.IsMasterClient())
				{
					PhotonNetwork.Destroy(((Component)spoofedPlayer).gameObject);
					SharePermissions.Logger.LogInfo((object)("Destroyed spoofed player object: " + ((Object)spoofedPlayer).name));
				}
				else
				{
					SharePermissions.Logger.LogWarning((object)"Cannot kick spoofed player - not master client and no valid identifiers");
				}
			}
			catch (Exception ex)
			{
				SharePermissions.Logger.LogError((object)("Failed to kick spoofed player: " + ex.Message));
			}
		}

		public static void addGhostPlayerButton(REPOPopupPage parent, string text, Player ghostPlayer, Action kickAction, Action banAction)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			string text2 = text;
			Player ghostPlayer2 = ghostPlayer;
			Action kickAction2 = kickAction;
			Action banAction2 = banAction;
			parent.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
				REPOButton val = MenuAPI.CreateREPOButton(text2, (Action)delegate
				{
					//IL_003b: Unknown result type (might be due to invalid IL or missing references)
					string message = $"Player: {ghostPlayer2.NickName}\nActorNumber: {ghostPlayer2.ActorNumber}\nNo avatar spawned!";
					createCustomPopupMenu("Ghost Player", new Color(1f, 0.67f, 0f), message, kickAction2, banAction2, "Kick", "Ban");
				}, scrollView, default(Vector2));
				if (text2.Length > 24)
				{
					Vector2 labelSize = val.GetLabelSize();
					labelSize.x = 250f;
					val.overrideButtonSize = labelSize;
					REPOTextScroller val2 = ((Component)val.labelTMP).gameObject.AddComponent<REPOTextScroller>();
					val2.maxCharacters = 24;
				}
				return ((REPOElement)val).rectTransform;
			}, 0f, 0f);
		}

		private static void KickGhostPlayer(Player ghostPlayer, string type)
		{
			try
			{
				if (ghostPlayer == null)
				{
					SharePermissions.Logger.LogWarning((object)"Cannot kick null ghost player");
					return;
				}
				string text = PlayerSteamIdCache.Instance.GetSteamId(ghostPlayer.ActorNumber) ?? ghostPlayer.UserId;
				if (!string.IsNullOrEmpty(text))
				{
					PlayerAvatar val = SemiFunc.PlayerGetFromSteamID(text);
					if ((Object)(object)val != (Object)null)
					{
						if (SemiFunc.IsMasterClient())
						{
							if (type == "kick")
							{
								NetworkManager.instance.KickPlayer(val);
							}
							else
							{
								NetworkManager.instance.BanPlayer(val);
							}
							SharePermissions.Logger.LogInfo((object)("Kicked ghost player via found avatar: " + ghostPlayer.NickName));
						}
						else
						{
							string fromSteamId = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance);
							string value = SharePermissions.SecretCode.Value;
							Events.SendCommand("KickPlayer", value, fromSteamId, new object[2] { text, type }, (ReceiverGroup)2);
							SharePermissions.Logger.LogInfo((object)("Sent kick command for ghost player: " + ghostPlayer.NickName));
						}
						return;
					}
				}
				if (SemiFunc.IsMasterClient())
				{
					PhotonNetwork.CloseConnection(ghostPlayer);
					SharePermissions.Logger.LogInfo((object)$"Closed connection for ghost player: {ghostPlayer.NickName} (ActorNumber: {ghostPlayer.ActorNumber})");
					return;
				}
				string fromSteamId2 = SemiFunc.PlayerGetSteamID(PlayerAvatar.instance);
				string value2 = SharePermissions.SecretCode.Value;
				Events.SendCommand("KickGhostPlayer", value2, fromSteamId2, new object[2]
				{
					ghostPlayer.ActorNumber.ToString(),
					type
				}, (ReceiverGroup)2);
				SharePermissions.Logger.LogInfo((object)$"Sent kick ghost command for: {ghostPlayer.NickName} (ActorNumber: {ghostPlayer.ActorNumber})");
			}
			catch (Exception ex)
			{
				SharePermissions.Logger.LogError((object)("Failed to kick ghost player: " + ex.Message));
			}
		}

		private static string GetSteamNickname(string steamIdString)
		{
			//IL_002e: 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_003e: 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)
			if (string.IsNullOrEmpty(steamIdString))
			{
				return null;
			}
			try
			{
				if (!ulong.TryParse(steamIdString, out var result))
				{
					return null;
				}
				SteamId val = default(SteamId);
				val.Value = result;
				SteamId val2 = val;
				if (!((SteamId)(ref val2)).IsValid)
				{
					return null;
				}
				Friend val3 = default(Friend);
				((Friend)(ref val3))..ctor(val2);
				string name = ((Friend)(ref val3)).Name;
				if (string.IsNullOrEmpty(name) || name == steamIdString)
				{
					return null;
				}
				return name;
			}
			catch (Exception ex)
			{
				SharePermissions.Logger.LogWarning((object)("Failed to get Steam nickname for " + steamIdString + ": " + ex.Message));
				return null;
			}
		}

		private static PlayerValidationResult ValidateNetworkPlayer(PlayerAvatar player)
		{
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				PlayerValidationResult result = default(PlayerValidationResult);
				result.IsValid = false;
				result.IsSpoofed = false;
				result.Reason = "Null player";
				return result;
			}
			try
			{
				PhotonView component = ((Component)player).GetComponent<PhotonView>();
				PlayerValidationResult result;
				if ((Object)(object)component == (Object)null)
				{
					result = default(PlayerValidationResult);
					result.IsValid = false;
					result.IsSpoofed = true;
					result.Reason = "No PhotonView component";
					return result;
				}
				if (component.Owner == null)
				{
					result = default(PlayerValidationResult);
					result.IsValid = false;
					result.IsSpoofed = true;
					result.Reason = "PhotonView has no owner";
					return result;
				}
				int actorNumber = component.Owner.ActorNumber;
				if (!PhotonNetwork.PlayerList.Any((Player p) => p.ActorNumber == actorNumber))
				{
					result = default(PlayerValidationResult);
					result.IsValid = false;
					result.IsSpoofed = true;
					result.Reason = $"ActorNumber {actorNumber} not in PhotonNetwork.PlayerList";
					return result;
				}
				string text = SemiFunc.PlayerGetSteamID(player);
				if (string.IsNullOrEmpty(text))
				{
					result = default(PlayerValidationResult);
					result.IsValid = false;
					result.IsSpoofed = false;
					result.Reason = "No Steam ID";
					return result;
				}
				if (!ulong.TryParse(text, out var result2))
				{
					result = default(PlayerValidationResult);
					result.IsValid = false;
					result.IsSpoofed = true;
					result.Reason = "Invalid Steam ID format: " + text;
					return result;
				}
				SteamId val = default(SteamId);
				val.Value = result2;
				SteamId val2 = val;
				if (!((SteamId)(ref val2)).IsValid)
				{
					result = default(PlayerValidationResult);
					result.IsValid = false;
					result.IsSpoofed = true;
					result.Reason = "Steam ID not valid: " + text;
					return result;
				}
				result = default(PlayerValidationResult);
				result.IsValid = true;
				result.IsSpoofed = false;
				result.Reason = "Valid";
				return result;
			}
			catch (Exception ex)
			{
				PlayerValidationResult result = default(PlayerValidationResult);
				result.IsValid = false;
				result.IsSpoofed = false;
				result.Reason = "Exception: " + ex.Message;
				return result;
			}
		}

		[IteratorStateMachine(typeof(<openPageInternal>d__21))]
		private static IEnumerator openPageInternal(REPOPopupPage page)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <openPageInternal>d__21(0)
			{
				page = page
			};
		}

		public static void openPage(REPOPopupPage page)
		{
			menuOpened = true;
			((MonoBehaviour)MenuManager.instance).StartCoroutine(openPageInternal(page));
		}

		private static void createCustomPopupMenu(string title, Color headerColor, string message, Action onLeftClicked, Action onRightClicked, string leftTitle = "Yes", string rightTitle = "No")
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)menuButtonPopup))
			{
				menuButtonPopup = ((Component)MenuManager.instance).gameObject.AddComponent<MenuButtonPopUp>();
			}
			menuButtonPopup.option1Event = new UnityEvent();
			menuButtonPopup.option2Event = new UnityEvent();
			if (onLeftClicked != null)
			{
				menuButtonPopup.option1Event.AddListener(new UnityAction(onLeftClicked.Invoke));
			}
			if (onRightClicked != null)
			{
				menuButtonPopup.option2Event.AddListener(new UnityAction(onRightClicked.Invoke));
			}
			MenuManager.instance.PagePopUpTwoOptions(menuButtonPopup, title, headerColor, message, leftTitle, rightTitle, true);
		}
	}
	[HarmonyPatch(typeof(LoadBalancingClient))]
	internal class LoadBalancingClientPatch
	{
		private const byte VoiceEventCode = 203;

		[HarmonyPatch("OnEvent")]
		[HarmonyPrefix]
		private static bool OnEvent_Prefix(EventData photonEvent)
		{
			if (photonEvent.Code == 203)
			{
				int sender = photonEvent.Sender;
				if (MutedPlayers.Instance.IsActorMuted(sender))
				{
					return false;
				}
				Room currentRoom = PhotonNetwork.CurrentRoom;
				Player val = ((currentRoom != null) ? currentRoom.GetPlayer(sender, false) : null);
				if (val != null)
				{
					foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
					{
						PhotonView val2 = ((item != null) ? ((Component)item).GetComponent<PhotonView>() : null);
						if ((Object)(object)val2 != (Object)null && val2.Owner != null && val2.Owner.ActorNumber == sender)
						{
							string text = SemiFunc.PlayerGetSteamID(item);
							if (!string.IsNullOrEmpty(text))
							{
								MutedPlayers.Instance.RegisterActorNumber(text, sender);
								if (MutedPlayers.Instance.IsMuted(text))
								{
									return false;
								}
								break;
							}
							break;
						}
					}
				}
			}
			return true;
		}
	}
	internal class Moderators
	{
		private static Moderators _instance;

		private HashSet<string> moderatorSteamIds = new HashSet<string>();

		private const string ModeratorIcon = "[M]";

		private const string HostIcon = "[H]";

		internal static Moderators Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new Moderators();
				}
				return _instance;
			}
		}

		public Moderators()
		{
			_instance = this;
		}

		public void AddModerator(string steamId)
		{
			if (!string.IsNullOrEmpty(steamId) && !moderatorSteamIds.Contains(steamId))
			{
				moderatorSteamIds.Add(steamId);
				SharePermissions.Logger.LogInfo((object)("Added moderator: " + steamId));
			}
		}

		public void RemoveModerator(string steamId)
		{
			if (moderatorSteamIds.Contains(steamId))
			{
				moderatorSteamIds.Remove(steamId);
				SharePermissions.Logger.LogInfo((object)("Removed moderator: " + steamId));
			}
		}

		public bool IsModerator(string steamId)
		{
			return !string.IsNullOrEmpty(steamId) && moderatorSteamIds.Contains(steamId);
		}

		public bool IsModerator(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			string steamId = SemiFunc.PlayerGetSteamID(player);
			return IsModerator(steamId);
		}

		public bool IsHost(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			PhotonView component = ((Component)player).GetComponent<PhotonView>();
			return (Object)(object)component != (Object)null && component.Owner != null && component.Owner.IsMasterClient;
		}

		public string GetPlayerDisplayName(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return "";
			}
			string text = SemiFunc.PlayerGetName(player);
			string playerIcon = GetPlayerIcon(player);
			return string.IsNullOrEmpty(playerIcon) ? text : ("<color=#FFD700>" + playerIcon + "</color> " + text);
		}

		public string GetPlayerIcon(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return "";
			}
			if (IsHost(player))
			{
				return "[H]";
			}
			if (IsModerator(player))
			{
				return "[M]";
			}
			return "";
		}

		public string GetPlayerEmoji(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return "";
			}
			if (IsHost(player))
			{
				return "[H]";
			}
			if (IsModerator(player))
			{
				return "[M]";
			}
			return "";
		}

		public List<string> GetAllModerators()
		{
			return moderatorSteamIds.ToList();
		}

		public void ClearModerators()
		{
			moderatorSteamIds.Clear();
			SharePermissions.Logger.LogInfo((object)"Cleared all moderators");
		}

		public int GetModeratorCount()
		{
			return moderatorSteamIds.Count;
		}

		public bool HasPermissions(PlayerAvatar player)
		{
			return IsHost(player) || IsModerator(player);
		}

		public bool HasPermissions(string steamId)
		{
			if (string.IsNullOrEmpty(steamId))
			{
				return false;
			}
			PlayerAvatar val = SemiFunc.PlayerGetFromSteamID(steamId);
			if ((Object)(object)val == (Object)null)
			{
				return IsModerator(steamId);
			}
			return HasPermissions(val);
		}

		public static void Init()
		{
			if (_instance == null)
			{
				new Moderators();
				SharePermissions.Logger.LogInfo((object)"Moderators system initialized");
			}
		}
	}
	internal class MutedPlayers
	{
		private static MutedPlayers _instance;

		private HashSet<string> mutedSteamIds = new HashSet<string>();

		private Dictionary<string, int> steamIdToActorNumber = new Dictionary<string, int>();

		internal static MutedPlayers Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new MutedPlayers();
				}
				return _instance;
			}
		}

		public MutedPlayers()
		{
			_instance = this;
		}

		public void MutePlayer(string steamId)
		{
			if (!string.IsNullOrEmpty(steamId) && !mutedSteamIds.Contains(steamId))
			{
				mutedSteamIds.Add(steamId);
				SharePermissions.Logger.LogInfo((object)("Muted player: " + steamId));
			}
		}

		public void UnmutePlayer(string steamId)
		{
			if (mutedSteamIds.Contains(steamId))
			{
				mutedSteamIds.Remove(steamId);
				SharePermissions.Logger.LogInfo((object)("Unmuted player: " + steamId));
			}
		}

		public bool IsMuted(string steamId)
		{
			return !string.IsNullOrEmpty(steamId) && mutedSteamIds.Contains(steamId);
		}

		public bool IsMuted(PlayerAvatar player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			string steamId = SemiFunc.PlayerGetSteamID(player);
			return IsMuted(steamId);
		}

		public void ToggleMute(string steamId)
		{
			if (IsMuted(steamId))
			{
				UnmutePlayer(steamId);
			}
			else
			{
				MutePlayer(steamId);
			}
		}

		public void RegisterActorNumber(string steamId, int actorNumber)
		{
			if (!string.IsNullOrEmpty(steamId))
			{
				steamIdToActorNumber[steamId] = actorNumber;
			}
		}

		public bool IsActorMuted(int actorNumber)
		{
			foreach (KeyValuePair<string, int> item in steamIdToActorNumber)
			{
				if (item.Value == actorNumber && mutedSteamIds.Contains(item.Key))
				{
					return true;
				}
			}
			return false;
		}

		public string GetSteamIdByActorNumber(int actorNumber)
		{
			foreach (KeyValuePair<string, int> item in steamIdToActorNumber)
			{
				if (item.Value == actorNumber)
				{
					return item.Key;
				}
			}
			return null;
		}

		public List<string> GetAllMutedPlayers()
		{
			return mutedSteamIds.ToList();
		}

		public void ClearMutedPlayers()
		{
			mutedSteamIds.Clear();
			steamIdToActorNumber.Clear();
			SharePermissions.Logger.LogInfo((object)"Cleared all muted players");
		}

		public int GetMutedCount()
		{
			return mutedSteamIds.Count;
		}

		public static void Init()
		{
			if (_instance == null)
			{
				new MutedPlayers();
				SharePermissions.Logger.LogInfo((object)"MutedPlayers system initialized");
			}
		}
	}
	[HarmonyPatch(typeof(NetworkConnect))]
	internal class NetworkConnectPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void Start_Postfix()
		{
			Events.Init();
			PlayerSteamIdCache.Init();
		}

		[HarmonyPatch("OnCreatedRoom")]
		[HarmonyPostfix]
		private static void OnCreatedRoom_Postfix()
		{
			SharePermissions.Logger.LogInfo((object)"onCreateRoom");
		}

		[HarmonyPatch("OnJoinedRoom")]
		[HarmonyPostfix]
		private static void OnJoinedRoom_Postfix()
		{
			SharePermissions.Logger.LogInfo((object)"onJoinRoom");
			PlayerSteamIdCache.Instance.RefreshFromAvatars();
			if (!SemiFunc.IsMasterClient())
			{
				PlayerAvatar instance = PlayerAvatar.instance;
				string fromSteamId = SemiFunc.PlayerGetSteamID(instance);
				string value = SharePermissions.SecretCode.Value;
				Events.SendCommand("InitModerator", value, fromSteamId, Array.Empty<object>(), (ReceiverGroup)2);
			}
		}

		[HarmonyPatch("OnDisconnected")]
		[HarmonyPostfix]
		private static void OnDisconnected_Postfix()
		{
			SharePermissions.Logger.LogInfo((object)"Left room - clearing all moderators");
			Moderators.Instance.ClearModerators();
			MutedPlayers.Instance.ClearMutedPlayers();
			PlayerSteamIdCache.Instance.Clear();
		}
	}
	[HarmonyPatch(typeof(NetworkManager))]
	internal class NetworkManagerPatch
	{
		[HarmonyPatch("OnPlayerEnteredRoom")]
		[HarmonyPostfix]
		private static void OnPlayerEnteredRoom_Postfix(Player newPlayer)
		{
			if (newPlayer == null)
			{
				return;
			}
			foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				PhotonView component = ((Component)item).GetComponent<PhotonView>();
				if (((component != null) ? component.Owner : null) == null || component.Owner.ActorNumber != newPlayer.ActorNumber)
				{
					continue;
				}
				string text = SemiFunc.PlayerGetSteamID(item);
				if (!string.IsNullOrEmpty(text))
				{
					PlayerSteamIdCache.Instance.RegisterPlayer(newPlayer.ActorNumber, text);
				}
				break;
			}
		}

		[HarmonyPatch("OnPlayerLeftRoom")]
		[HarmonyPostfix]
		private static void OnPlayerLeftRoom_Postfix(Player otherPlayer)
		{
			if (otherPlayer == null)
			{
				return;
			}
			string text = PlayerSteamIdCache.Instance.GetSteamId(otherPlayer.ActorNumber) ?? otherPlayer.UserId;
			if (!string.IsNullOrEmpty(text))
			{
				if (Moderators.Instance.IsModerator(text))
				{
					Moderators.Instance.RemoveModerator(text);
					SharePermissions.Logger.LogInfo((object)("Player " + otherPlayer.NickName + " (" + text + ") left - removed moderator status"));
				}
				if (MutedPlayers.Instance.IsMuted(text))
				{
					MutedPlayers.Instance.UnmutePlayer(text);
					SharePermissions.Logger.LogInfo((object)("Player " + otherPlayer.NickName + " (" + text + ") left - removed mute status"));
				}
			}
			PlayerSteamIdCache.Instance.UnregisterPlayer(otherPlayer.ActorNumber);
		}
	}
	internal class PlayerSteamIdCache
	{
		private static PlayerSteamIdCache _instance;

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

		internal static PlayerSteamIdCache Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new PlayerSteamIdCache();
				}
				return _instance;
			}
		}

		public PlayerSteamIdCache()
		{
			_instance = this;
		}

		public void RegisterPlayer(int actorNumber, string steamId)
		{
			if (actorNumber > 0 && !string.IsNullOrEmpty(steamId))
			{
				if (actorToSteamId.TryGetValue(actorNumber, out string value) && value != steamId)
				{
					SharePermissions.Logger.LogWarning((object)$"ActorNumber {actorNumber} already registered with different SteamID: {value} -> {steamId}");
				}
				actorToSteamId[actorNumber] = steamId;
				SharePermissions.Logger.LogInfo((object)$"Registered player mapping: ActorNumber {actorNumber} -> SteamID {steamId}");
			}
		}

		public string GetSteamId(int actorNumber)
		{
			if (actorToSteamId.TryGetValue(actorNumber, out string value))
			{
				return value;
			}
			return null;
		}

		public string GetSteamId(Player player)
		{
			if (player == null)
			{
				return null;
			}
			return GetSteamId(player.ActorNumber);
		}

		public void UnregisterPlayer(int actorNumber)
		{
			if (actorToSteamId.Remove(actorNumber))
			{
				SharePermissions.Logger.LogInfo((object)$"Unregistered player mapping for ActorNumber {actorNumber}");
			}
		}

		public void Clear()
		{
			actorToSteamId.Clear();
			SharePermissions.Logger.LogInfo((object)"Cleared player Steam ID cache");
		}

		public void RefreshFromAvatars()
		{
			List<PlayerAvatar> list = SemiFunc.PlayerGetAll();
			if (list == null)
			{
				return;
			}
			foreach (PlayerAvatar item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				PhotonView component = ((Component)item).GetComponent<PhotonView>();
				if (((component != null) ? component.Owner : null) != null)
				{
					int actorNumber = component.Owner.ActorNumber;
					string text = SemiFunc.PlayerGetSteamID(item);
					if (!string.IsNullOrEmpty(text))
					{
						RegisterPlayer(actorNumber, text);
					}
				}
			}
		}

		public static void Init()
		{
			if (_instance == null)
			{
				new PlayerSteamIdCache();
				SharePermissions.Logger.LogInfo((object)"PlayerSteamIdCache initialized");
			}
		}
	}
	[HarmonyPatch(typeof(RunManager))]
	internal class RunPatch
	{
		private static bool lastKeyState;

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void Update_Postfix(RunPatch __instance)
		{
			bool key = Input.GetKey((KeyCode)32);
			if (!lastKeyState && key)
			{
				if (SemiFunc.RunIsLobbyMenu())
				{
					Menu.toggleMenu();
				}
				lastKeyState = key;
			}
			else if (lastKeyState && !key)
			{
				lastKeyState = key;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("RestartScene")]
		[HarmonyWrapSafe]
		private static void RestartScene_Prefix(RunManager __instance)
		{
			if (SharePermissions.IsReturningToLobby && __instance.restarting && !__instance.restartingDone && (Object)(object)GameDirector.instance != (Object)null && GameDirector.instance.PlayerList.All((PlayerAvatar p) => p.outroDone))
			{
				SharePermissions.IsReturningToLobby = false;
				NetworkManager.instance.DestroyAll();
			}
		}
	}
	[BepInPlugin("RED.SharePermissions", "SharePermissions", "1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SharePermissions : BaseUnityPlugin
	{
		private static string _logPath;

		public static bool IsReturningToLobby;

		internal static SharePermissions Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		public static ConfigEntry<string> SecretCode { get; private set; }

		private static string LogPath
		{
			get
			{
				if (!string.IsNullOrEmpty(_logPath))
				{
					return _logPath;
				}
				try
				{
					_logPath = Path.Combine(Paths.ConfigPath, "sharepermissions.log");
				}
				catch
				{
					_logPath = Path.Combine(Application.persistentDataPath, "sharepermissions.log");
				}
				return _logPath;
			}
		}

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Patch();
			Menu.Init();
			Moderators.Init();
			Configuration(((BaseUnityPlugin)this).Config);
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		public static void LogWrite(string line)
		{
			try
			{
				string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
				string text2 = "[" + text + "] " + line;
				string directoryName = Path.GetDirectoryName(LogPath);
				if (!Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				File.AppendAllText(LogPath, text2 + Environment.NewLine);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"[SharePermissions] Log save failed: {arg}");
			}
		}

		internal void Configuration(ConfigFile config)
		{
			SecretCode = config.Bind<string>("General", "SecretCode", "", "Code for share permission");
		}

		public static void ReturnLobbyClick()
		{
			IsReturningToLobby = true;
			RunManager instance = RunManager.instance;
			int num = ((instance.levelCurrent == instance.levelShop) ? 1 : 0);
			instance.ChangeLevel(true, SemiFunc.RunIsArena(), (ChangeLevelType)3);
			SemiFunc.StatSetSaveLevel(num);
			instance.loadLevel = num;
			StatsManager.instance.SaveFileSave();
		}

		public static void StartGameClick()
		{
			RunManager instance = RunManager.instance;
			instance.ChangeLevel(false, SemiFunc.RunIsArena(), (ChangeLevelType)0);
		}

		internal void Patch()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
		}
	}
}