Decompiled source of BanEnforcer v4.0.1

BepInEx\plugins\Omniscye-BanEnforcer\BanList.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using MenuLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using Steamworks.Data;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0")]
[assembly: AssemblyProduct("BanList")]
[assembly: AssemblyTitle("BanList")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.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 Empress.REPO.BanEnforcer
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.empress.repo.banenforcer", "Empress Ban Enforcer", "2.1.0")]
	public class EmpressBanEnforcerPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.empress.repo.banenforcer";

		public const string PluginName = "Empress Ban Enforcer";

		public const string PluginVersion = "2.1.0";

		private const float EscapeButtonNudgeY = 3.7f;

		internal static ManualLogSource LogSrc;

		private Harmony? _harmony;

		private bool _show;

		private Rect _win = new Rect(60f, 120f, 940f, 540f);

		private Vector2 _scrollPlayers;

		private Vector2 _scrollBanned;

		private Vector2 _scrollSteam;

		private string _manualSteamBan = string.Empty;

		private string _manualBanReason = string.Empty;

		private string _playerSearch = string.Empty;

		private string _bannedSearch = string.Empty;

		private string _steamSearch = string.Empty;

		private string _uiStatus = "Ready to enforce Steam bans.";

		private ConfigEntry<KeyCode> _toggleKey;

		private ConfigEntry<KeyCode> _debugDumpKey;

		private ConfigEntry<bool> _verboseLogsConfig;

		private ConfigEntry<bool> _logLocalIdsConfig;

		public static EmpressBanEnforcerPlugin Instance { get; private set; }

		internal static bool WindowOpen
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance._show;
				}
				return false;
			}
		}

		public static void OpenUI()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = Object.FindObjectOfType<EmpressBanEnforcerPlugin>();
			}
			if ((Object)(object)Instance != (Object)null)
			{
				Instance.OpenWindow();
			}
		}

		private void Awake()
		{
			Instance = this;
			((Object)this).hideFlags = (HideFlags)61;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			LogSrc = ((BaseUnityPlugin)this).Logger;
			_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "ToggleKey", (KeyCode)287, "Key to open or close the ban enforcer window.");
			_debugDumpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "DebugDumpKey", (KeyCode)288, "Key to dump debug information to the BepInEx log.");
			_verboseLogsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "VerboseLogs", false, "Enable extra ban enforcement logging.");
			_logLocalIdsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "LogLocalIds", false, "Include local player Steam ID details in verbose logs.");
			EmpressBanManager.VerboseLogs = _verboseLogsConfig.Value;
			EmpressBanManager.LogLocalIds = _logLocalIdsConfig.Value;
		}

		private IEnumerator Start()
		{
			yield return null;
			yield return null;
			try
			{
				_harmony = new Harmony("com.empress.repo.banenforcer");
				EmpressBanPatcher.Apply(_harmony);
				EmpressBanManager.EnsureExists();
				EmpressSteamLobbyGate.EnsureRegistered();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"[EmpressBan] Init error: {arg}");
			}
			try
			{
				if (SteamClient.IsValid)
				{
					string text = ((object)SteamClient.SteamId/*cast due to .constrained prefix*/).ToString();
					if (!string.IsNullOrEmpty(text))
					{
						if (PhotonNetwork.AuthValues == null)
						{
							PhotonNetwork.AuthValues = new AuthenticationValues();
						}
						PhotonNetwork.AuthValues.UserId = text;
					}
				}
			}
			catch
			{
			}
			try
			{
				MenuAPI.AddElementToEscapeMenu(new BuilderDelegate(BuildEscapeButton));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[EmpressBan] MenuLib register failed: " + ex.Message));
			}
		}

		private void BuildEscapeButton(Transform parent)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			REPOButton val = MenuAPI.CreateREPOButton("<size=20><b>BAN LIST</b></size>", (Action)OpenUI, parent, Vector2.zero);
			if ((Object)(object)val != (Object)null)
			{
				((MonoBehaviour)this).StartCoroutine(PositionEscapeButton(val, parent));
			}
		}

		private IEnumerator PositionEscapeButton(REPOButton button, Transform parent)
		{
			yield return null;
			yield return null;
			if ((Object)(object)button == (Object)null || (Object)(object)parent == (Object)null)
			{
				yield break;
			}
			MenuButton menuButton = button.menuButton;
			MenuButton val = null;
			List<MenuButton> list = new List<MenuButton>();
			List<float> list2 = new List<float>();
			MenuButton[] componentsInChildren = ((Component)parent).GetComponentsInChildren<MenuButton>(true);
			foreach (MenuButton val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)menuButton))
				{
					list.Add(val2);
					list2.Add(parent.InverseTransformPoint(((Component)val2).transform.position).y);
					if ((val2.buttonTextString ?? string.Empty).Replace(" ", string.Empty).IndexOf("MainMenu", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val = val2;
					}
				}
			}
			if ((Object)(object)val == (Object)null || list.Count == 0)
			{
				yield break;
			}
			Vector3 val3 = parent.InverseTransformPoint(((Component)val).transform.position);
			float num = 40f;
			list2.Sort();
			float num2 = float.MaxValue;
			for (int j = 1; j < list2.Count; j++)
			{
				float num3 = list2[j] - list2[j - 1];
				if (num3 > 1f && num3 < num2)
				{
					num2 = num3;
				}
			}
			if (num2 < float.MaxValue)
			{
				num = num2;
			}
			MenuButton val4 = null;
			float num4 = float.MinValue;
			foreach (MenuButton item in list)
			{
				float y = parent.InverseTransformPoint(((Component)item).transform.position).y;
				if (!(y >= val3.y - 1f) && !(item.buttonTextString ?? string.Empty).ToLowerInvariant().Contains("quit") && y > num4)
				{
					num4 = y;
					val4 = item;
				}
			}
			Vector2 val6 = default(Vector2);
			if ((Object)(object)val4 != (Object)null)
			{
				Vector3 val5 = parent.InverseTransformPoint(((Component)val4).transform.position);
				((Vector2)(ref val6))..ctor(val5.x, val5.y + num);
			}
			else
			{
				((Vector2)(ref val6))..ctor(val3.x, val3.y - num);
			}
			Vector3 localPosition = ((Component)button).transform.localPosition;
			((Component)button).transform.localPosition = new Vector3(val6.x, val6.y + 3.7f, localPosition.z);
		}

		private void Update()
		{
			//IL_0026: 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)
			EmpressBanManager.VerboseLogs = _verboseLogsConfig.Value;
			EmpressBanManager.LogLocalIds = _logLocalIdsConfig.Value;
			if (Input.GetKeyDown(_toggleKey.Value))
			{
				if (_show)
				{
					CloseWindow();
				}
				else
				{
					OpenWindow();
				}
				return;
			}
			if (_show)
			{
				RefreshUiInputCapture();
				if (Input.GetKeyDown((KeyCode)27))
				{
					CloseWindow();
					return;
				}
			}
			if (Input.GetKeyDown(_debugDumpKey.Value))
			{
				EmpressBanManager.DumpDebugInfo();
			}
		}

		private void OpenWindow()
		{
			_show = true;
			RefreshUiInputCapture();
			SetUiStatus("Ban enforcer opened.");
		}

		private void CloseWindow()
		{
			_show = false;
			if ((Object)(object)CursorManager.instance != (Object)null)
			{
				CursorManager.instance.unlockTimer = 0f;
			}
		}

		private void SetUiStatus(string message)
		{
			if (!string.IsNullOrWhiteSpace(message))
			{
				_uiStatus = message.Trim();
			}
		}

		private void RefreshUiInputCapture()
		{
			if ((Object)(object)CursorManager.instance != (Object)null)
			{
				CursorManager.instance.unlockTimer = -1234f;
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		private void OnGUI()
		{
			//IL_0010: 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_002b: Expected O, but got Unknown
			//IL_0026: 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)
			if (_show)
			{
				_win = GUI.Window(20033, _win, new WindowFunction(DrawWindow), "EMPRESS BAN ENFORCER");
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label(_uiStatus, Array.Empty<GUILayoutOption>());
			GUILayout.Label((PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) ? "You are the host. Bans enforce immediately." : "You are not the host. Bans are stored and enforce when you host.", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawPlayersColumn();
			DrawBannedColumn();
			DrawSteamColumn();
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Steam64:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(64f) });
			_manualSteamBan = GUILayout.TextField(_manualSteamBan, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(190f) });
			GUILayout.Label("Reason:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(54f) });
			_manualBanReason = GUILayout.TextField(_manualBanReason, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(240f) });
			if (GUILayout.Button("Ban Steam ID", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }))
			{
				ManualBan();
			}
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Dump Debug", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
			{
				EmpressBanManager.DumpDebugInfo();
			}
			if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				CloseWindow();
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
			GUI.DragWindow(new Rect(0f, 0f, 100000f, 24f));
		}

		private void DrawPlayersColumn()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) });
			GUILayout.Label("<b>In-Room Players</b>", Array.Empty<GUILayoutOption>());
			_playerSearch = GUILayout.TextField(_playerSearch, Array.Empty<GUILayoutOption>());
			_scrollPlayers = GUILayout.BeginScrollView(_scrollPlayers, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(340f) });
			if (PhotonNetwork.InRoom)
			{
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val in playerList)
				{
					if (val == null || val.IsLocal)
					{
						continue;
					}
					string text = (((Object)(object)EmpressBanManager.Instance != (Object)null) ? EmpressBanManager.Instance.ResolveSteam64For(val) : string.Empty);
					string text2 = val.NickName + "  (" + (string.IsNullOrEmpty(text) ? "no steam id" : text) + ")";
					if (Matches(text2, _playerSearch))
					{
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
						GUILayout.Label(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) });
						if (GUILayout.Button("Ban", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
						{
							EmpressBanManager.BanPlayer(val);
							SetUiStatus("Banned " + val.NickName + ".");
						}
						GUILayout.EndHorizontal();
					}
				}
			}
			else
			{
				GUILayout.Label("Not in a room.", Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawBannedColumn()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(320f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>Banned</b>", Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Clear All", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				EmpressBanManager.ClearAllLocalBans();
				SetUiStatus("Cleared all local bans.");
			}
			GUILayout.EndHorizontal();
			_bannedSearch = GUILayout.TextField(_bannedSearch, Array.Empty<GUILayoutOption>());
			_scrollBanned = GUILayout.BeginScrollView(_scrollBanned, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(340f) });
			foreach (EmpressBanManager.BanRecordSnapshot item in EmpressBanManager.BanRecordsSnapshot())
			{
				string text = (string.IsNullOrEmpty(item.DisplayName) ? item.LastSeenName : item.DisplayName);
				string text2 = string.Format("{0}  ({1})", string.IsNullOrEmpty(text) ? "Unknown" : text, item.SteamId);
				if (Matches(text2 + " " + item.Reason, _bannedSearch))
				{
					GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
					if (GUILayout.Button("Unban", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
					{
						EmpressBanManager.RemoveSteamKey(item.Key);
						SetUiStatus($"Unbanned {item.SteamId}.");
					}
					GUILayout.EndHorizontal();
					if (!string.IsNullOrEmpty(item.Reason))
					{
						GUILayout.Label("<size=11>" + item.Reason + "</size>", Array.Empty<GUILayoutOption>());
					}
					GUILayout.EndVertical();
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawSteamColumn()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) });
			GUILayout.Label("<b>Steam Lobby</b>", Array.Empty<GUILayoutOption>());
			_steamSearch = GUILayout.TextField(_steamSearch, Array.Empty<GUILayoutOption>());
			_scrollSteam = GUILayout.BeginScrollView(_scrollSteam, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(340f) });
			ulong num = (SteamClient.IsValid ? SteamClient.SteamId.Value : 0);
			foreach (KeyValuePair<ulong, string> item in EmpressBanManager.SteamLobbySnapshot())
			{
				if (item.Key == num)
				{
					continue;
				}
				string text = string.Format("{0}  ({1})", string.IsNullOrEmpty(item.Value) ? "Unknown" : item.Value, item.Key);
				if (Matches(text, _steamSearch))
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) });
					if (EmpressBanManager.IsSteamIdBanned(item.Key))
					{
						GUILayout.Label("Banned", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
					}
					else if (GUILayout.Button("Ban", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						EmpressBanManager.BanBySteamId(item.Key, item.Value, "Banned from Steam lobby list");
						SetUiStatus($"Banned {item.Value} ({item.Key}).");
					}
					GUILayout.EndHorizontal();
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void ManualBan()
		{
			if (!ulong.TryParse(_manualSteamBan.Trim(), out var result) || result == 0L)
			{
				SetUiStatus("Enter a valid Steam64 ID.");
				return;
			}
			EmpressBanManager.BanBySteamId(result, null, string.IsNullOrWhiteSpace(_manualBanReason) ? "Manual ban" : _manualBanReason.Trim());
			SetUiStatus($"Banned Steam64 {result}.");
			_manualSteamBan = string.Empty;
			_manualBanReason = string.Empty;
		}

		private static bool Matches(string text, string search)
		{
			if (string.IsNullOrWhiteSpace(search))
			{
				return true;
			}
			return text.IndexOf(search.Trim(), StringComparison.OrdinalIgnoreCase) >= 0;
		}
	}
	public static class EmpressBanPatcher
	{
		public static void Apply(Harmony harmony)
		{
			harmony.PatchAll(typeof(EmpressBanPatcher).Assembly);
		}
	}
	public class EmpressBanManager : MonoBehaviourPunCallbacks
	{
		[Serializable]
		public sealed class SaveModel
		{
			public List<string> keys = new List<string>();

			public List<BanRecordModel> records = new List<BanRecordModel>();
		}

		[Serializable]
		public sealed class BanRecordModel
		{
			public string steamId = string.Empty;

			public string displayName = string.Empty;

			public string reason = string.Empty;

			public string lastSeenName = string.Empty;

			public string createdUtc = string.Empty;
		}

		private sealed class BanRecord
		{
			public string Key = string.Empty;

			public ulong SteamId;

			public string DisplayName = string.Empty;

			public string Reason = string.Empty;

			public string LastSeenName = string.Empty;

			public DateTime CreatedUtc = DateTime.UtcNow;
		}

		public sealed class BanRecordSnapshot
		{
			public string Key { get; set; } = string.Empty;

			public ulong SteamId { get; set; }

			public string DisplayName { get; set; } = string.Empty;

			public string Reason { get; set; } = string.Empty;

			public string LastSeenName { get; set; } = string.Empty;

			public DateTime CreatedUtc { get; set; }
		}

		private sealed class PlayerInfo
		{
			public string NickName = string.Empty;

			public string SteamId = string.Empty;

			public int ActorNumber;

			public DateTime LastSeenUtc;

			public bool HasSid => !string.IsNullOrEmpty(SteamId);
		}

		public static bool VerboseLogs;

		public static bool LogLocalIds;

		private const float KickRetrySeconds = 1.75f;

		private readonly Dictionary<string, BanRecord> _banRecords = new Dictionary<string, BanRecord>(StringComparer.OrdinalIgnoreCase);

		private readonly HashSet<ulong> _pendingPhotonEnforcement = new HashSet<ulong>();

		private readonly Dictionary<int, PlayerInfo> _playerCache = new Dictionary<int, PlayerInfo>();

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

		private readonly Dictionary<ulong, string> _steamLobbyMembers = new Dictionary<ulong, string>();

		private readonly Dictionary<string, List<ulong>> _nameToSteamIds = new Dictionary<string, List<ulong>>(StringComparer.Ordinal);

		private static string? _savePath;

		public static EmpressBanManager Instance { get; private set; }

		private static string SavePath
		{
			get
			{
				if (!string.IsNullOrEmpty(_savePath))
				{
					return _savePath;
				}
				try
				{
					_savePath = Path.Combine(Paths.ConfigPath, "RepoBanList.json");
				}
				catch
				{
					_savePath = Path.Combine(Application.persistentDataPath, "RepoBanList.json");
				}
				return _savePath;
			}
		}

		public static event Action<ulong, string>? BanApplied;

		public static event Action<ulong>? BanRemoved;

		public static void EnsureExists()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				GameObject val = new GameObject("EmpressBanManager")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<EmpressBanManager>();
				((Object)Instance).hideFlags = (HideFlags)61;
				Instance.LoadLocal();
				if (VerboseLogs)
				{
					Debug.Log((object)"[EmpressBan] Manager created (Steam-only).");
				}
			}
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(UpdatePlayerInfoRoutine());
			ForceRefreshAll();
		}

		private void OnDestroy()
		{
			try
			{
				SaveLocal();
			}
			catch
			{
			}
			if (Instance == this)
			{
				Instance = null;
			}
		}

		private IEnumerator UpdatePlayerInfoRoutine()
		{
			while (true)
			{
				yield return (object)new WaitForSecondsRealtime(2f);
				ForceRefreshAll();
			}
		}

		public void ForceRefreshAll()
		{
			RefreshSteamLobbyMap();
			if (PhotonNetwork.InRoom)
			{
				UpdatePlayerCache();
				EnforceExistingBans();
				EnforcePendingBans();
			}
		}

		internal void RefreshSteamLobbyMap()
		{
			//IL_0017: 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_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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)SteamManager.instance == (Object)null)
				{
					return;
				}
				Lobby currentLobby = SteamManager.instance.currentLobby;
				SteamId id = ((Lobby)(ref currentLobby)).Id;
				if (!((SteamId)(ref id)).IsValid)
				{
					return;
				}
				_steamLobbyMembers.Clear();
				_nameToSteamIds.Clear();
				foreach (Friend member in ((Lobby)(ref currentLobby)).Members)
				{
					Friend current = member;
					ulong value = current.Id.Value;
					string text = ((Friend)(ref current)).Name ?? string.Empty;
					_steamLobbyMembers[value] = text;
					if (IsSteamIdBanned(value))
					{
						QueuePendingEnforcement(value, string.IsNullOrWhiteSpace(text) ? $"Steam lobby member {value}" : text);
					}
					if (!string.IsNullOrEmpty(text))
					{
						if (!_nameToSteamIds.TryGetValue(text, out List<ulong> value2))
						{
							value2 = new List<ulong>();
							_nameToSteamIds[text] = value2;
						}
						if (!value2.Contains(value))
						{
							value2.Add(value);
						}
					}
				}
			}
			catch
			{
			}
		}

		public string ResolveSteam64For(Player p)
		{
			if (p == null)
			{
				return string.Empty;
			}
			PlayerInfo orCreatePlayerInfo = GetOrCreatePlayerInfo(p);
			if (!string.IsNullOrEmpty(orCreatePlayerInfo.SteamId))
			{
				return orCreatePlayerInfo.SteamId;
			}
			string text = ExtractSteam64FromCustomProps(p);
			if (!string.IsNullOrEmpty(text))
			{
				orCreatePlayerInfo.SteamId = text;
				return text;
			}
			if (!string.IsNullOrEmpty(p.NickName) && _nameToSteamIds.TryGetValue(p.NickName, out List<ulong> value) && value.Count > 0)
			{
				orCreatePlayerInfo.SteamId = value[0].ToString();
			}
			return orCreatePlayerInfo.SteamId ?? string.Empty;
		}

		private string ExtractSteam64FromCustomProps(Player? player, Hashtable? changedProps = null)
		{
			Hashtable val = changedProps ?? ((player != null) ? player.CustomProperties : null);
			if (val == null)
			{
				return string.Empty;
			}
			string[] array = new string[5] { "steamId", "steamID", "steamid", "SteamId", "STEAMID" };
			foreach (string text in array)
			{
				if (!((Dictionary<object, object>)(object)val).TryGetValue((object)text, out object value))
				{
					continue;
				}
				string text2 = value?.ToString();
				if (!string.IsNullOrEmpty(text2) && text2 != "0")
				{
					if (VerboseLogs && player != null && (!player.IsLocal || LogLocalIds))
					{
						Debug.Log((object)("[EmpressBan] Found Steam ID for " + player.NickName + ": " + text2 + " (" + text + ")"));
					}
					return text2;
				}
			}
			if (!string.IsNullOrEmpty((player != null) ? player.UserId : null) && player.UserId.All(char.IsDigit) && player.UserId.Length >= 10)
			{
				return player.UserId;
			}
			return string.Empty;
		}

		private void UpdatePlayerCache()
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val == null)
				{
					continue;
				}
				PlayerInfo orCreatePlayerInfo = GetOrCreatePlayerInfo(val);
				bool hasSid = orCreatePlayerInfo.HasSid;
				orCreatePlayerInfo.NickName = val.NickName;
				orCreatePlayerInfo.ActorNumber = val.ActorNumber;
				orCreatePlayerInfo.LastSeenUtc = DateTime.UtcNow;
				orCreatePlayerInfo.SteamId = ResolveSteam64For(val);
				TouchBanRecord(orCreatePlayerInfo.SteamId, orCreatePlayerInfo.NickName);
				if (!hasSid && orCreatePlayerInfo.HasSid && IsSteam64Banned(orCreatePlayerInfo.SteamId))
				{
					if (VerboseLogs)
					{
						Debug.Log((object)("[EmpressBan] Newly identified banned player " + orCreatePlayerInfo.NickName + "; enforcing kick."));
					}
					EnforceKick(val, orCreatePlayerInfo.SteamId, "newly identified");
				}
			}
		}

		private PlayerInfo GetOrCreatePlayerInfo(Player player)
		{
			if (!_playerCache.TryGetValue(player.ActorNumber, out PlayerInfo value))
			{
				value = new PlayerInfo();
				_playerCache[player.ActorNumber] = value;
			}
			return value;
		}

		private static string PrefixSteam(string id)
		{
			return "steam:" + id;
		}

		private static string PrefixSteam(ulong steamId)
		{
			return PrefixSteam(steamId.ToString());
		}

		private static string NormalizeReason(string? reason)
		{
			if (!string.IsNullOrWhiteSpace(reason))
			{
				return reason.Trim();
			}
			return string.Empty;
		}

		private static string NormalizeDisplayName(string? displayName)
		{
			if (!string.IsNullOrWhiteSpace(displayName))
			{
				return displayName.Trim();
			}
			return string.Empty;
		}

		private void TouchBanRecord(string sidText, string displayName)
		{
			if (!ulong.TryParse(sidText, out var result))
			{
				return;
			}
			string key = PrefixSteam(result);
			if (!_banRecords.TryGetValue(key, out BanRecord value))
			{
				return;
			}
			bool flag = false;
			if (!string.IsNullOrWhiteSpace(displayName))
			{
				string text = displayName.Trim();
				if (!string.Equals(value.LastSeenName, text, StringComparison.Ordinal))
				{
					value.LastSeenName = text;
					flag = true;
				}
				if (string.IsNullOrWhiteSpace(value.DisplayName))
				{
					value.DisplayName = text;
					flag = true;
				}
			}
			if (flag)
			{
				SaveLocal();
			}
		}

		private void UpsertBanRecord(ulong steamId, string? displayName, string? reason)
		{
			string key = PrefixSteam(steamId);
			if (!_banRecords.TryGetValue(key, out BanRecord value))
			{
				value = new BanRecord
				{
					Key = key,
					SteamId = steamId,
					CreatedUtc = DateTime.UtcNow
				};
				_banRecords[key] = value;
			}
			string text = NormalizeDisplayName(displayName);
			string text2 = NormalizeReason(reason);
			if (!string.IsNullOrWhiteSpace(text))
			{
				value.DisplayName = text;
				value.LastSeenName = text;
			}
			if (!string.IsNullOrWhiteSpace(text2))
			{
				value.Reason = text2;
			}
		}

		private void QueuePendingEnforcement(ulong steamId, string sourceLabel)
		{
			if (steamId != 0L)
			{
				_pendingPhotonEnforcement.Add(steamId);
				if (VerboseLogs)
				{
					Debug.Log((object)$"[EmpressBan] Queued enforcement for Steam64 {steamId} from {sourceLabel}.");
				}
			}
		}

		private void EnforceExistingBans()
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val != null && !val.IsLocal && ulong.TryParse(ResolveSteam64For(val), out var result) && IsSteamIdBanned(result))
				{
					PlayerInfo orCreatePlayerInfo = GetOrCreatePlayerInfo(val);
					if (VerboseLogs)
					{
						Debug.Log((object)$"[EmpressBan] Enforcing active ban on {orCreatePlayerInfo.NickName} ({result}).");
					}
					EnforceKick(val, result.ToString(), "active ban scan");
				}
			}
		}

		private void EnforcePendingBans()
		{
			if (_pendingPhotonEnforcement.Count == 0)
			{
				return;
			}
			ulong[] array = _pendingPhotonEnforcement.ToArray();
			foreach (ulong num in array)
			{
				if (TryEnforceBySteamId(num, "pending enforcement"))
				{
					_pendingPhotonEnforcement.Remove(num);
				}
			}
		}

		private bool TryEnforceBySteamId(ulong steamId, string reasonContext)
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val != null && !val.IsLocal)
				{
					string text = ResolveSteam64For(val);
					if (ulong.TryParse(text, out var result) && result == steamId)
					{
						return EnforceKick(val, text, reasonContext);
					}
				}
			}
			return false;
		}

		public static void BanPlayer(Player p)
		{
			if (p != null && !((Object)(object)Instance == (Object)null))
			{
				if (!ulong.TryParse(Instance.ResolveSteam64For(p), out var result))
				{
					Debug.LogWarning((object)("[EmpressBan] Could not resolve Steam64 for " + p.NickName + ". Use the Steam panel or manual field."));
				}
				else
				{
					BanBySteamId(result, p.NickName, "Banned from in-room player list");
				}
			}
		}

		public static void BanBySteamId(ulong steamId, string? displayName = null, string? reason = null)
		{
			if (steamId == 0L || (Object)(object)Instance == (Object)null)
			{
				return;
			}
			bool num = IsSteamIdBanned(steamId);
			Instance.UpsertBanRecord(steamId, displayName, reason);
			Instance.QueuePendingEnforcement(steamId, "ban list");
			Instance.SaveLocal();
			if (!Instance.TryEnforceBySteamId(steamId, "manual ban") && VerboseLogs)
			{
				Debug.Log((object)$"[EmpressBan] Stored ban for Steam64 {steamId}. Enforcement will apply as soon as that player resolves in-room.");
			}
			if (num)
			{
				return;
			}
			try
			{
				EmpressBanManager.BanApplied?.Invoke(steamId, NormalizeReason(reason));
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[EmpressBan] BanApplied handler failed: " + ex.Message));
			}
		}

		public static void RemoveSteamKey(string key)
		{
			if ((Object)(object)Instance == (Object)null || string.IsNullOrWhiteSpace(key) || !Instance._banRecords.Remove(key))
			{
				return;
			}
			ulong num = 0uL;
			if (ulong.TryParse(key.Replace("steam:", string.Empty), out var result))
			{
				num = result;
				Instance._pendingPhotonEnforcement.Remove(result);
			}
			Instance.SaveLocal();
			if (num == 0L)
			{
				return;
			}
			try
			{
				EmpressBanManager.BanRemoved?.Invoke(num);
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[EmpressBan] BanRemoved handler failed: " + ex.Message));
			}
		}

		public static void RemoveSteamId(ulong steamId)
		{
			RemoveSteamKey(PrefixSteam(steamId));
		}

		public static void ClearAllLocalBans()
		{
			if (!((Object)(object)Instance == (Object)null))
			{
				Instance._banRecords.Clear();
				Instance._pendingPhotonEnforcement.Clear();
				Instance.SaveLocal();
			}
		}

		public static List<string> LocalSteamKeysSnapshot()
		{
			return Instance?._banRecords.Keys.Where((string key) => key.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)).OrderBy<string, string>((string key) => key, StringComparer.OrdinalIgnoreCase).ToList() ?? new List<string>();
		}

		public static List<BanRecordSnapshot> BanRecordsSnapshot()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				return new List<BanRecordSnapshot>();
			}
			return (from record in Instance._banRecords.Values.OrderByDescending((BanRecord record) => record.CreatedUtc).ThenBy<BanRecord, string>((BanRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase)
				select new BanRecordSnapshot
				{
					Key = record.Key,
					SteamId = record.SteamId,
					DisplayName = record.DisplayName,
					Reason = record.Reason,
					LastSeenName = record.LastSeenName,
					CreatedUtc = record.CreatedUtc
				}).ToList();
		}

		public static int PendingEnforcementCount()
		{
			return Instance?._pendingPhotonEnforcement.Count ?? 0;
		}

		public static Dictionary<ulong, string> SteamLobbySnapshot()
		{
			Dictionary<ulong, string> dictionary = new Dictionary<ulong, string>();
			if ((Object)(object)Instance == (Object)null)
			{
				return dictionary;
			}
			foreach (KeyValuePair<ulong, string> steamLobbyMember in Instance._steamLobbyMembers)
			{
				dictionary[steamLobbyMember.Key] = steamLobbyMember.Value;
			}
			return dictionary;
		}

		public static bool IsSteamIdBanned(ulong steamId)
		{
			if ((Object)(object)Instance == (Object)null || steamId == 0L)
			{
				return false;
			}
			return Instance._banRecords.ContainsKey(PrefixSteam(steamId));
		}

		private bool IsSteam64Banned(string sidText)
		{
			if (ulong.TryParse(sidText, out var result))
			{
				return IsSteamIdBanned(result);
			}
			return false;
		}

		public override void OnJoinedRoom()
		{
			((MonoBehaviourPunCallbacks)this).OnJoinedRoom();
			_playerCache.Clear();
			((MonoBehaviour)this).StartCoroutine(DelayedScan());
		}

		private IEnumerator DelayedScan()
		{
			yield return (object)new WaitForSecondsRealtime(1f);
			ForceRefreshAll();
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			((MonoBehaviourPunCallbacks)this).OnPlayerEnteredRoom(newPlayer);
			if (VerboseLogs)
			{
				Debug.Log((object)$"[EmpressBan] Player entered: {newPlayer.NickName} (Actor: {newPlayer.ActorNumber})");
			}
			string text = ResolveSteam64For(newPlayer);
			TouchBanRecord(text, newPlayer.NickName);
			if (IsSteam64Banned(text))
			{
				if (VerboseLogs)
				{
					Debug.Log((object)("[EmpressBan] Immediately detected banned player: " + newPlayer.NickName));
				}
				EnforceKick(newPlayer, text, "player joined");
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(DelayedCheck(newPlayer));
			}
		}

		public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
			((MonoBehaviourPunCallbacks)this).OnPlayerPropertiesUpdate(targetPlayer, changedProps);
			if (targetPlayer != null)
			{
				PlayerInfo orCreatePlayerInfo = GetOrCreatePlayerInfo(targetPlayer);
				orCreatePlayerInfo.NickName = targetPlayer.NickName;
				orCreatePlayerInfo.ActorNumber = targetPlayer.ActorNumber;
				orCreatePlayerInfo.LastSeenUtc = DateTime.UtcNow;
				string text = ExtractSteam64FromCustomProps(targetPlayer, changedProps);
				if (string.IsNullOrWhiteSpace(text))
				{
					text = ResolveSteam64For(targetPlayer);
				}
				if (!string.IsNullOrWhiteSpace(text))
				{
					orCreatePlayerInfo.SteamId = text;
					TouchBanRecord(text, targetPlayer.NickName);
				}
				if (!targetPlayer.IsLocal && IsSteam64Banned(orCreatePlayerInfo.SteamId))
				{
					EnforceKick(targetPlayer, orCreatePlayerInfo.SteamId, "player properties update");
				}
			}
		}

		private IEnumerator DelayedCheck(Player player)
		{
			yield return (object)new WaitForSecondsRealtime(3f);
			if (player == null || !PhotonNetwork.PlayerList.Contains(player))
			{
				yield break;
			}
			string text = ResolveSteam64For(player);
			TouchBanRecord(text, player.NickName);
			if (IsSteam64Banned(text))
			{
				if (VerboseLogs)
				{
					Debug.Log((object)("[EmpressBan] Delayed detection of banned player: " + player.NickName));
				}
				EnforceKick(player, text, "delayed join check");
			}
		}

		public override void OnPlayerLeftRoom(Player otherPlayer)
		{
			((MonoBehaviourPunCallbacks)this).OnPlayerLeftRoom(otherPlayer);
			_lastKickTime.Remove(otherPlayer.ActorNumber);
			((MonoBehaviour)this).StartCoroutine(DelayedCacheCleanup(otherPlayer.ActorNumber));
		}

		private IEnumerator DelayedCacheCleanup(int actorNumber)
		{
			yield return (object)new WaitForSecondsRealtime(30f);
			_playerCache.Remove(actorNumber);
		}

		private bool EnforceKick(Player target, string id, string reasonContext)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (target == null || target.IsLocal)
			{
				return false;
			}
			if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom)
			{
				return false;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (_lastKickTime.TryGetValue(target.ActorNumber, out var value) && realtimeSinceStartup - value < 1.75f)
			{
				return true;
			}
			_lastKickTime[target.ActorNumber] = realtimeSinceStartup;
			if (VerboseLogs)
			{
				Debug.Log((object)$"[EmpressBan] Kicking {target.NickName} (Steam64: {id}, Actor: {target.ActorNumber}, Context: {reasonContext}).");
			}
			RaiseEventOptions val = new RaiseEventOptions();
			val.TargetActors = new int[1] { target.ActorNumber };
			RaiseEventOptions val2 = val;
			PhotonNetwork.RaiseEvent((byte)199, (object)null, val2, SendOptions.SendReliable);
			return true;
		}

		private static DateTime ParseStoredUtc(string raw)
		{
			if (DateTime.TryParse(raw, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result))
			{
				return result;
			}
			return DateTime.UtcNow;
		}

		private void SaveLocal()
		{
			try
			{
				SaveModel saveModel = new SaveModel
				{
					keys = _banRecords.Keys.OrderBy<string, string>((string key) => key, StringComparer.OrdinalIgnoreCase).ToList(),
					records = (from record in _banRecords.Values.OrderBy<BanRecord, string>((BanRecord record) => record.Key, StringComparer.OrdinalIgnoreCase)
						select new BanRecordModel
						{
							steamId = record.SteamId.ToString(),
							displayName = record.DisplayName,
							reason = record.Reason,
							lastSeenName = record.LastSeenName,
							createdUtc = record.CreatedUtc.ToString("O", CultureInfo.InvariantCulture)
						}).ToList()
				};
				string contents = JsonConvert.SerializeObject((object)saveModel, (Formatting)1);
				Directory.CreateDirectory(Path.GetDirectoryName(SavePath) ?? Paths.ConfigPath);
				File.WriteAllText(SavePath, contents);
				if (VerboseLogs)
				{
					Debug.Log((object)$"[EmpressBan] Saved {saveModel.records.Count} local steam bans to {SavePath}");
				}
			}
			catch (Exception arg)
			{
				Debug.LogWarning((object)$"[EmpressBan] SaveLocal failed: {arg}");
			}
		}

		private void LoadLocal()
		{
			try
			{
				_banRecords.Clear();
				if (!File.Exists(SavePath))
				{
					return;
				}
				SaveModel saveModel = JsonConvert.DeserializeObject<SaveModel>(File.ReadAllText(SavePath));
				if (saveModel?.records != null)
				{
					foreach (BanRecordModel record in saveModel.records)
					{
						if (ulong.TryParse(record.steamId, out var result) && result != 0L)
						{
							string key = PrefixSteam(result);
							_banRecords[key] = new BanRecord
							{
								Key = key,
								SteamId = result,
								DisplayName = NormalizeDisplayName(record.displayName),
								Reason = NormalizeReason(record.reason),
								LastSeenName = NormalizeDisplayName(record.lastSeenName),
								CreatedUtc = ParseStoredUtc(record.createdUtc)
							};
						}
					}
				}
				if (saveModel?.keys != null)
				{
					foreach (string key3 in saveModel.keys)
					{
						if (!string.IsNullOrWhiteSpace(key3) && key3.StartsWith("steam:", StringComparison.OrdinalIgnoreCase) && ulong.TryParse(key3.Replace("steam:", string.Empty), out var result2) && result2 != 0L)
						{
							string key2 = PrefixSteam(result2);
							if (!_banRecords.ContainsKey(key2))
							{
								_banRecords[key2] = new BanRecord
								{
									Key = key2,
									SteamId = result2,
									CreatedUtc = DateTime.UtcNow
								};
							}
						}
					}
				}
				if (VerboseLogs)
				{
					Debug.Log((object)$"[EmpressBan] Loaded {_banRecords.Count} local steam bans from {SavePath}");
				}
			}
			catch (Exception arg)
			{
				Debug.LogWarning((object)$"[EmpressBan] LoadLocal failed: {arg}");
			}
		}

		public static void DumpDebugInfo()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Debug.Log((object)"[EmpressBan] Manager not initialized");
				return;
			}
			Debug.Log((object)"[EmpressBan] === DEBUG INFO ===");
			Debug.Log((object)$"[EmpressBan] Local steam keys: {Instance._banRecords.Count}");
			foreach (BanRecord item in Instance._banRecords.Values.OrderBy<BanRecord, string>((BanRecord record) => record.Key, StringComparer.OrdinalIgnoreCase))
			{
				Debug.Log((object)("[EmpressBan]   - " + item.Key + " | Name: '" + item.DisplayName + "' | Note: '" + item.Reason + "' | LastSeen: '" + item.LastSeenName + "'"));
			}
			Debug.Log((object)$"[EmpressBan] Steam lobby members: {Instance._steamLobbyMembers.Count}");
			foreach (KeyValuePair<ulong, string> steamLobbyMember in Instance._steamLobbyMembers)
			{
				Debug.Log((object)$"[EmpressBan]   - {steamLobbyMember.Value} ({steamLobbyMember.Key})");
			}
			Debug.Log((object)$"[EmpressBan] Pending enforcement: {Instance._pendingPhotonEnforcement.Count}");
			foreach (ulong item2 in Instance._pendingPhotonEnforcement.OrderBy((ulong result) => result))
			{
				Debug.Log((object)$"[EmpressBan]   - {item2}");
			}
			Debug.Log((object)$"[EmpressBan] Cached players: {Instance._playerCache.Count}");
			foreach (KeyValuePair<int, PlayerInfo> item3 in Instance._playerCache)
			{
				PlayerInfo value = item3.Value;
				Debug.Log((object)$"[EmpressBan]   Actor{item3.Key}: {value.NickName} | Steam64: '{value.SteamId}'");
			}
			Debug.Log((object)$"[EmpressBan] Current Photon players: {PhotonNetwork.PlayerList.Length}");
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				string text = Instance.ResolveSteam64For(val) ?? "Unknown";
				bool flag = Instance.IsSteam64Banned(text);
				Debug.Log((object)$"[EmpressBan]   {val.NickName} | Steam64: '{text}' | Banned: {flag}");
			}
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "BanPlayer")]
	public static class Patch_NetworkManager_BanPlayer
	{
		private static void Postfix(PlayerAvatar _playerAvatar)
		{
			try
			{
				if (!((Object)(object)_playerAvatar?.photonView == (Object)null))
				{
					int ownerActorNr = _playerAvatar.photonView.OwnerActorNr;
					Room currentRoom = PhotonNetwork.CurrentRoom;
					Player val = ((currentRoom != null) ? currentRoom.GetPlayer(ownerActorNr, false) : null);
					if (val == null)
					{
						Debug.LogWarning((object)$"[EmpressBan] Could not resolve Player for actor {ownerActorNr}");
						return;
					}
					Debug.Log((object)("[EmpressBan] NetworkManager.BanPlayer called for " + val.NickName + " (steam-only)"));
					EmpressBanManager.BanPlayer(val);
				}
			}
			catch (Exception arg)
			{
				Debug.LogWarning((object)$"[EmpressBan] BanPlayer postfix failed: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(MenuCursor), "Show")]
	public static class Patch_MenuCursor_Show
	{
		private static bool Prefix()
		{
			return !EmpressBanEnforcerPlugin.WindowOpen;
		}
	}
	[HarmonyPatch(typeof(CursorManager), "Unlock")]
	public static class Patch_CursorManager_Unlock
	{
		private static bool Prefix()
		{
			return !EmpressBanEnforcerPlugin.WindowOpen;
		}
	}
	internal static class EmpressSteamLobbyGate
	{
		private static bool _registered;

		public static void EnsureRegistered()
		{
			if (_registered)
			{
				return;
			}
			_registered = true;
			try
			{
				SteamMatchmaking.OnLobbyMemberJoined += OnLobbyMemberJoined;
				SteamMatchmaking.OnLobbyMemberLeave += OnLobbyMemberLeft;
				Debug.Log((object)"[EmpressBan] SteamLobbyGate registered");
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[EmpressBan] SteamLobbyGate registration failed: " + ex.Message));
				_registered = false;
			}
		}

		private static void OnLobbyMemberJoined(Lobby lobby, Friend friend)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				EmpressBanManager.Instance?.RefreshSteamLobbyMap();
				if ((Object)(object)SteamManager.instance == (Object)null)
				{
					return;
				}
				SteamId id = ((Lobby)(ref SteamManager.instance.currentLobby)).Id;
				if (!((SteamId)(ref id)).IsValid || SteamId.op_Implicit(((Lobby)(ref lobby)).Id) != SteamId.op_Implicit(((Lobby)(ref SteamManager.instance.currentLobby)).Id) || !((Lobby)(ref SteamManager.instance.currentLobby)).IsOwnedBy(SteamClient.SteamId))
				{
					return;
				}
				ulong value = friend.Id.Value;
				if (EmpressBanManager.IsSteamIdBanned(value))
				{
					EmpressBanManager.Instance?.ForceRefreshAll();
					if (EmpressBanManager.VerboseLogs)
					{
						Debug.Log((object)$"[EmpressBan] Banned Steam lobby member detected ({value}). Waiting for Photon resolution so the host can remove them cleanly.");
					}
				}
			}
			catch (Exception ex)
			{
				if (EmpressBanManager.VerboseLogs)
				{
					Debug.LogWarning((object)("[EmpressBan] SteamLobbyGate.OnLobbyMemberJoined error: " + ex.Message));
				}
			}
		}

		private static void OnLobbyMemberLeft(Lobby lobby, Friend friend)
		{
			EmpressBanManager.Instance?.RefreshSteamLobbyMap();
		}
	}
	public static class VippyBan
	{
		public const string ApiVersion = "1.0.0";

		public static bool IsReady => (Object)(object)EmpressBanManager.Instance != (Object)null;

		public static event Action<ulong, string> Banned
		{
			add
			{
				EmpressBanManager.BanApplied += value;
			}
			remove
			{
				EmpressBanManager.BanApplied -= value;
			}
		}

		public static event Action<ulong> Unbanned
		{
			add
			{
				EmpressBanManager.BanRemoved += value;
			}
			remove
			{
				EmpressBanManager.BanRemoved -= value;
			}
		}

		public static bool Ban(ulong steamId, string? reason = null, string? displayName = null)
		{
			if (steamId == 0L || (Object)(object)EmpressBanManager.Instance == (Object)null)
			{
				return false;
			}
			EmpressBanManager.BanBySteamId(steamId, displayName, string.IsNullOrWhiteSpace(reason) ? "VippyBan auto-ban" : reason);
			return true;
		}

		public static bool Ban(Player player, string? reason = null)
		{
			if (player == null || (Object)(object)EmpressBanManager.Instance == (Object)null)
			{
				return false;
			}
			if (!TryResolveSteamId(player, out var steamId))
			{
				return false;
			}
			EmpressBanManager.BanBySteamId(steamId, player.NickName, string.IsNullOrWhiteSpace(reason) ? "VippyBan auto-ban" : reason);
			return true;
		}

		public static bool Unban(ulong steamId)
		{
			if (steamId == 0L || (Object)(object)EmpressBanManager.Instance == (Object)null)
			{
				return false;
			}
			EmpressBanManager.RemoveSteamId(steamId);
			return true;
		}

		public static bool IsBanned(ulong steamId)
		{
			return EmpressBanManager.IsSteamIdBanned(steamId);
		}

		public static IReadOnlyList<ulong> GetBannedSteamIds()
		{
			return (from record in EmpressBanManager.BanRecordsSnapshot()
				select record.SteamId).ToList();
		}

		public static bool TryResolveSteamId(Player player, out ulong steamId)
		{
			steamId = 0uL;
			if (player == null || (Object)(object)EmpressBanManager.Instance == (Object)null)
			{
				return false;
			}
			if (ulong.TryParse(EmpressBanManager.Instance.ResolveSteam64For(player), out steamId))
			{
				return steamId != 0;
			}
			return false;
		}
	}
}