Decompiled source of Lethal Admin v1.9.2

LethalAdmin.dll

Decompiled 4 months 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.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalAdmin.Bans;
using LethalAdmin.Logging;
using LethalAdmin.Patches;
using LethalAdmin.UI;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Steamworks;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LethalAdmin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("An admin tool for lethal company")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7dfb186685f827125279f05bfd747a979761b8da")]
[assembly: AssemblyProduct("LethalAdmin")]
[assembly: AssemblyTitle("LethalAdmin")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace LethalAdmin
{
	public static class KickBanTools
	{
		public class PlayerInfo
		{
			public string Username;

			public ulong SteamID;

			public bool Connected;

			public WalkieMode WalkieMode;

			public bool IsPlayerDead;

			public PlayerControllerB PlayerController;

			public override string ToString()
			{
				return $"{Username} ({SteamID}@steam)";
			}
		}

		public static void UpdateKickedIDs()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return;
			}
			StartOfRound.Instance.KickedClientIds.Clear();
			foreach (BanInfo ban in BanHandler.GetBans())
			{
				StartOfRound.Instance.KickedClientIds.Add(ban.SteamID);
			}
		}

		public static List<PlayerInfo> GetPlayers()
		{
			return StartOfRound.Instance.allPlayerScripts.Select((PlayerControllerB player, int i) => new PlayerInfo
			{
				Username = player.playerUsername,
				SteamID = player.playerSteamId,
				Connected = StartOfRound.Instance.fullyLoadedPlayers.Contains((ulong)i),
				WalkieMode = GetWalkieMode(player),
				IsPlayerDead = player.isPlayerDead,
				PlayerController = player
			}).ToList();
		}

		public static void BanPlayer(PlayerInfo playerInfo, string reason = null)
		{
			if (playerInfo.SteamID == 0L)
			{
				LethalLogger.AddLog(new Log($"[Ban] {playerInfo} is not a player or steam is disabled, when not using steam bans are not possible!", "Error"));
				return;
			}
			if (BanHandler.AddBan(playerInfo.SteamID, playerInfo.Username, reason))
			{
				LethalLogger.AddLog(new Log($"[Ban] {playerInfo} has been banned"));
			}
			else
			{
				LethalLogger.AddLog(new Log($"[Ban] Could not ban {playerInfo} as this user is already banned", "Warning"));
			}
			KickPlayer(playerInfo);
		}

		public static void UnbanPlayer(ulong steamID)
		{
			if (BanHandler.RemoveBan(steamID))
			{
				LethalLogger.AddLog(new Log($"[Ban] {steamID}@steam has been unbanned"));
			}
			else
			{
				LethalLogger.AddLog(new Log($"[Ban] Could not unban {steamID}@steam as this user is not banned", "Warning"));
			}
			StartOfRound.Instance.KickedClientIds.Remove(steamID);
		}

		public static void KickPlayer(PlayerInfo playerInfo)
		{
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			for (int i = 0; i < allPlayerScripts.Length; i++)
			{
				PlayerControllerB val = allPlayerScripts[i];
				if (!(val.playerUsername != playerInfo.Username) && val.playerSteamId == playerInfo.SteamID)
				{
					StartOfRound.Instance.KickPlayer(i);
					LethalLogger.AddLog(new Log($"[Kick] {playerInfo} has been kicked (id={i})"));
				}
			}
		}

		public static void ShowProfile(string username, ulong steamId)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SteamFriends.OpenUserOverlay(SteamId.op_Implicit(steamId), "steamid");
			LethalLogger.AddLog(new Log($"[ProfileCheck] {username} ({steamId}@steam))"));
		}

		private static WalkieMode GetWalkieMode(PlayerControllerB player)
		{
			WalkieMode result = WalkieMode.Disabled;
			if (player.holdingWalkieTalkie)
			{
				result = WalkieMode.Listening;
			}
			if (player.speakingToWalkieTalkie)
			{
				result = WalkieMode.Talking;
			}
			return result;
		}
	}
	[BepInPlugin("gamendegamer.lethaladmin", "Lethal Admin", "1.9.2")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginVersion = "1.9.2";

		public static Plugin Instance;

		public static string ConfigFolder;

		public static bool DebugMode;

		private readonly Harmony _harmony = new Harmony("LethalAdmin");

		private const string ConfigSection = "Lethal Admin";

		private ConfigEntry<string> _bans;

		private ConfigEntry<int> _minVotesConfig;

		private ConfigEntry<bool> _lockLeverConfig;

		private ConfigEntry<bool> _requireSteam;

		private ConfigEntry<bool> _furnitureLocked;

		private ConfigEntry<int> _buttonHeight;

		private ConfigEntry<bool> _openUIOnStart;

		public int MinVotes
		{
			get
			{
				return _minVotesConfig.Value;
			}
			set
			{
				_minVotesConfig.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public bool LockLever
		{
			get
			{
				return _lockLeverConfig.Value;
			}
			set
			{
				_lockLeverConfig.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public bool RequireSteam
		{
			get
			{
				return _requireSteam.Value;
			}
			set
			{
				_requireSteam.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public bool FurnitureLocked
		{
			get
			{
				return _furnitureLocked.Value;
			}
			set
			{
				_furnitureLocked.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public int ButtonHeight
		{
			get
			{
				return _buttonHeight.Value;
			}
			set
			{
				_buttonHeight.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public bool OpenUIOnStart
		{
			get
			{
				return _openUIOnStart.Value;
			}
			set
			{
				_openUIOnStart.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Starting Lethal Admin");
			_harmony.PatchAll(typeof(BuildingPatch));
			_harmony.PatchAll(typeof(ConnectionPatch));
			_harmony.PatchAll(typeof(RoundPatch));
			_harmony.PatchAll(typeof(MenuPatch));
			_harmony.PatchAll(typeof(ControllerPatch));
			_harmony.PatchAll(typeof(VotingPatch));
			Instance = this;
			_bans = ((BaseUnityPlugin)this).Config.Bind<string>("Lethal Admin", "bans", "", "The steam IDs of all banned players, comma seperated. [deprecated]");
			_minVotesConfig = ((BaseUnityPlugin)this).Config.Bind<int>("Lethal Admin", "minVotes", 1, "The minimum amount of votes before the autopilot starts. Use a value of 1 to disable.");
			_lockLeverConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Lethal Admin", "leverLock", false, "When enabled (true) the ship departure lever can only be used by the host.");
			_requireSteam = ((BaseUnityPlugin)this).Config.Bind<bool>("Lethal Admin", "requireSteam", true, "When enabled, clients attempting to join without a valid steamID will be denied.");
			_furnitureLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("Lethal Admin", "furnitureLocked", false, "When enabled, this will only allow the host to move the furniture. This does NOT prevent furniture from being taken out of storage");
			_buttonHeight = ((BaseUnityPlugin)this).Config.Bind<int>("Lethal Admin", "buttonHeight", 200, "The height the open UI button appears at in the pause menu. Recommended to change from within the game.");
			_openUIOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("Lethal Admin", "openUIOnStart", true, "Whether to automatically show the UI when the user goes to the pause menu the first time.");
			ConfigFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath);
			BanHandler.LoadBans();
			if (_bans.Value != "Deprecated!")
			{
				BanHandler.LoadDeprecated(_bans.Value.Split(","));
				_bans.Value = "Deprecated!";
				((BaseUnityPlugin)this).Config.Save();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Finished starting Lethal Admin");
		}
	}
	public static class RoundUtils
	{
		private static StartOfRound StartOfRound => StartOfRound.Instance;

		private static TimeOfDay TimeOfDay => TimeOfDay.Instance;

		public static bool IsVoteOverrideAvailable()
		{
			int num = StartOfRound.connectedPlayersAmount + 1;
			int livingPlayers = StartOfRound.livingPlayers;
			if (num - livingPlayers == 0)
			{
				return false;
			}
			return !TimeOfDay.shipLeavingAlertCalled;
		}

		public static void OverrideVotes()
		{
			LethalLogger.AddLog(new Log("[Voting] Vote override triggered"));
			TimeOfDay instance = TimeOfDay.Instance;
			int num = (instance.votesForShipToLeaveEarly = StartOfRound.Instance.connectedPlayersAmount);
			instance.SetShipLeaveEarlyClientRpc(TimeOfDay.normalizedTimeOfDay + 0.1f, num);
		}
	}
	public enum WalkieMode
	{
		Disabled,
		Listening,
		Talking
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LethalAdmin";

		public const string PLUGIN_NAME = "LethalAdmin";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace LethalAdmin.UI
{
	public class BanView : IView
	{
		private static BanInfo _selectedBan;

		public string GetViewName()
		{
			return "Bans";
		}

		public void DrawView()
		{
			if (_selectedBan == null)
			{
				DrawBanList();
			}
			else
			{
				DrawBanInfo();
			}
		}

		private static void DrawBanList()
		{
			foreach (BanInfo ban in BanHandler.GetBans())
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"{ban.Username} ({ban.SteamID}@steam)", LethalAdminUI.WideLabelOptions);
				if (GUILayout.Button("View ban info", Array.Empty<GUILayoutOption>()))
				{
					_selectedBan = ban;
				}
				GUILayout.EndHorizontal();
			}
		}

		private static void DrawBanInfo()
		{
			if (GUILayout.Button("<- Back to ban list", Array.Empty<GUILayoutOption>()))
			{
				_selectedBan = null;
				return;
			}
			GUILayout.Space(20f);
			GUILayout.Label($"User: {_selectedBan.Username} ({_selectedBan.SteamID}@steam)", Array.Empty<GUILayoutOption>());
			GUILayout.Label("Ban reason: " + _selectedBan.BanReason, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			if (GUILayout.Button("Unban user", Array.Empty<GUILayoutOption>()))
			{
				KickBanTools.UnbanPlayer(_selectedBan.SteamID);
				_selectedBan = null;
			}
			else if (GUILayout.Button("Open steam profile", Array.Empty<GUILayoutOption>()))
			{
				KickBanTools.ShowProfile(_selectedBan.Username, _selectedBan.SteamID);
			}
		}
	}
	public interface IView
	{
		string GetViewName();

		void DrawView();
	}
	public class LethalAdminUI : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<IView, string> <>9__29_0;

			public static Func<Transform, bool> <>9__38_0;

			public static UnityAction <>9__38_2;

			internal string <.ctor>b__29_0(IView view)
			{
				return view.GetViewName();
			}

			internal bool <PrepareGui>b__38_0(Transform child)
			{
				return ((Object)child).name == "Resume";
			}

			internal void <PrepareGui>b__38_2()
			{
				_guiEnabled = true;
			}
		}

		private static readonly ManualLogSource ManualLogger = Logger.CreateLogSource("Admin UI");

		private readonly GUILayoutOption[] _options = (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(900f),
			GUILayout.Height(400f)
		};

		private readonly GUILayoutOption[] _minimizedOptions = (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(300f),
			GUILayout.Height(20f)
		};

		public static readonly GUILayoutOption[] LabelOptions = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) };

		public static readonly GUILayoutOption[] WideLabelOptions = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(500f) };

		private static bool _guiMinimized;

		private static bool _guiEnabled = true;

		private static LethalAdminUI _instance;

		private static bool _menuButtonFailed;

		private static RectTransform _menuButtonTransform;

		private int _toolbarInt;

		private bool _menuOpen;

		private Rect _windowRect;

		private readonly IView[] _toolbarViews = new IView[4]
		{
			new UsersView(),
			new SettingsView(),
			new BanView(),
			new WhitelistView()
		};

		private readonly string[] _toolbarStrings;

		private Vector2 _scrollPosition;

		private bool _menuAlwaysOpen;

		public static GUIStyle RedText { get; private set; }

		public static GUIStyle WhiteText { get; private set; }

		public static GUIStyle YellowText { get; private set; }

		public LethalAdminUI()
		{
			_toolbarStrings = _toolbarViews.Select((IView view) => view.GetViewName()).ToArray();
		}

		private void Awake()
		{
			if ((Object)(object)_instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)_instance);
			}
			_instance = this;
			_guiEnabled = Plugin.Instance.OpenUIOnStart;
		}

		private void OnDestroy()
		{
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		public static void SetMenuForAll(bool value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				new GameObject("Lethal Admin UI").AddComponent<LethalAdminUI>();
				ManualLogger.LogInfo((object)"Generating UI");
			}
			_instance._menuOpen = value;
		}

		public static void UpdateButtonHeight(int newHeight)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localPosition = ((Transform)_menuButtonTransform).localPosition;
			((Transform)_menuButtonTransform).localPosition = new Vector3(localPosition.x, (float)newHeight, localPosition.z);
		}

		private void OnGUI()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)StartOfRound.Instance).IsServer || Plugin.DebugMode)
			{
				if (!Object.op_Implicit((Object)(object)_menuButtonTransform) && !_menuButtonFailed)
				{
					PrepareGui();
				}
				if ((_menuOpen || _menuAlwaysOpen) && _guiEnabled)
				{
					int controlID = GUIUtility.GetControlID((FocusType)2);
					_windowRect = GUILayout.Window(controlID, _windowRect, new WindowFunction(DrawUI), "Lethal Admin Menu V1.9.2", _guiMinimized ? _minimizedOptions : _options);
				}
			}
		}

		private void DrawUI(int windowID)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (_guiMinimized)
			{
				if (GUILayout.Button("Expand UI", Array.Empty<GUILayoutOption>()))
				{
					_guiMinimized = false;
				}
			}
			else
			{
				ExpandedUI();
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 500f));
		}

		private void ExpandedUI()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			_scrollPosition = GUILayout.BeginScrollView(_scrollPosition, GUI.skin.box);
			_toolbarViews[_toolbarInt].DrawView();
			GUILayout.FlexibleSpace();
			GUILayout.EndScrollView();
			DefaultUI();
			GUILayout.EndVertical();
		}

		private void DefaultUI()
		{
			_toolbarInt = GUILayout.Toolbar(_toolbarInt, _toolbarStrings, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (GUILayout.Button("Toggle ship lights", Array.Empty<GUILayoutOption>()))
			{
				StartOfRound.Instance.shipRoomLights.ToggleShipLights();
			}
			if (RoundUtils.IsVoteOverrideAvailable() && GUILayout.Button("Override vote (will trigger auto pilot)", Array.Empty<GUILayoutOption>()))
			{
				RoundUtils.OverrideVotes();
			}
			GUILayout.Space(20f);
			_menuAlwaysOpen = GUILayout.Toggle(_menuAlwaysOpen, "Always show menu", Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Minimize UI", Array.Empty<GUILayoutOption>()))
			{
				_guiMinimized = true;
				_menuAlwaysOpen = false;
			}
			if (GUILayout.Button("Close UI", Array.Empty<GUILayoutOption>()))
			{
				_guiEnabled = false;
			}
		}

		private static void PrepareGui()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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)
			//IL_0072: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label);
			val.normal.textColor = Color.yellow;
			YellowText = val;
			GUIStyle val2 = new GUIStyle(GUI.skin.label);
			val2.normal.textColor = Color.red;
			RedText = val2;
			GUIStyle val3 = new GUIStyle(GUI.skin.label);
			val3.normal.textColor = Color.white;
			WhiteText = val3;
			GUI.skin.toggle = new GUIStyle(GUI.skin.toggle)
			{
				stretchWidth = false
			};
			Transform parent = StartOfRound.Instance.localPlayerController.quickMenuManager.mainButtonsPanel.transform;
			GameObject val4 = (from Transform child in (IEnumerable)parent
				where ((Object)child).name == "Resume"
				select Object.Instantiate<GameObject>(((Component)child).gameObject, parent)).FirstOrDefault();
			Button val5 = default(Button);
			if ((Object)(object)val4 == (Object)null || !val4.TryGetComponent<Button>(ref val5) || !val4.TryGetComponent<RectTransform>(ref _menuButtonTransform))
			{
				FailedUI(val4);
				return;
			}
			TextMeshProUGUI componentInChildren = val4.GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				FailedUI(val4);
				return;
			}
			((TMP_Text)componentInChildren).text = "> Open Admin UI";
			val5.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = val5.onClick;
			object obj = <>c.<>9__38_2;
			if (obj == null)
			{
				UnityAction val6 = delegate
				{
					_guiEnabled = true;
				};
				<>c.<>9__38_2 = val6;
				obj = (object)val6;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			UpdateButtonHeight(Plugin.Instance.ButtonHeight);
		}

		private static void FailedUI(GameObject obj)
		{
			_menuButtonFailed = true;
			LethalLogger.AddLog(new Log("Failed to create the UI button, restart your game!"));
			ManualLogger.LogWarning((object)"Could not find all components to create new button!");
			Object.Destroy((Object)(object)obj);
		}
	}
	public class SettingsView : IView
	{
		private static string _minVotes = Plugin.Instance.MinVotes.ToString();

		private static int _buttonHeight = Plugin.Instance.ButtonHeight;

		private static bool _leverLocked = Plugin.Instance.LockLever;

		private static bool _requireSteam = Plugin.Instance.RequireSteam;

		private static bool _furnitureLocked = Plugin.Instance.FurnitureLocked;

		private static string _settingsErrorMessage = "";

		public string GetViewName()
		{
			return "Settings & Logs";
		}

		public void DrawView()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Minimum departure votes: ", Array.Empty<GUILayoutOption>());
			_minVotes = GUILayout.TextField(_minVotes, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Open UI button height: ", Array.Empty<GUILayoutOption>());
			_buttonHeight = (int)GUILayout.HorizontalSlider((float)_buttonHeight, 0f, 400f, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			_leverLocked = GUILayout.Toggle(_leverLocked, "Only owner can start ship", Array.Empty<GUILayoutOption>());
			_requireSteam = GUILayout.Toggle(_requireSteam, "Require valid steam ID", Array.Empty<GUILayoutOption>());
			_furnitureLocked = GUILayout.Toggle(_furnitureLocked, "Only host can move furniture", Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Apply settings", Array.Empty<GUILayoutOption>()))
			{
				try
				{
					int num = int.Parse(_minVotes);
					if (num < 1)
					{
						_minVotes = Plugin.Instance.MinVotes.ToString();
						_settingsErrorMessage = "Minimum departure votes can not be negative.";
					}
					else
					{
						Plugin.Instance.MinVotes = num;
						Plugin.Instance.ButtonHeight = _buttonHeight;
						Plugin.Instance.LockLever = _leverLocked;
						Plugin.Instance.RequireSteam = _requireSteam;
						Plugin.Instance.FurnitureLocked = _furnitureLocked;
						_settingsErrorMessage = "Successfully saved the settings!";
					}
				}
				catch (FormatException)
				{
					_minVotes = Plugin.Instance.MinVotes.ToString();
					_settingsErrorMessage = "New minimum departure votes is not a valid integer.";
				}
			}
			GUILayout.Label(_settingsErrorMessage, LethalAdminUI.YellowText, Array.Empty<GUILayoutOption>());
			IEnumerable<Log> logs = LethalLogger.GetLogs();
			GUILayout.Label("Logs:", Array.Empty<GUILayoutOption>());
			foreach (Log item in logs)
			{
				GUILayout.Label(item.GetTimeFormattedString(), Array.Empty<GUILayoutOption>());
			}
			LethalAdminUI.UpdateButtonHeight(_buttonHeight);
		}
	}
	public class UsersView : IView
	{
		private static KickBanTools.PlayerInfo _selectedPlayer;

		private static string _banReason;

		private static StartOfRound Round => StartOfRound.Instance;

		public string GetViewName()
		{
			return "Users";
		}

		public void DrawView()
		{
			if (_selectedPlayer == null)
			{
				DrawUserList();
			}
			else
			{
				DrawUserInfo();
			}
		}

		private static void DrawUserList()
		{
			GUILayout.Label("Yellow - Not connected", LethalAdminUI.YellowText, LethalAdminUI.LabelOptions);
			GUILayout.Label("Red - Dead", LethalAdminUI.RedText, LethalAdminUI.LabelOptions);
			GUILayout.Space(10f);
			List<KickBanTools.PlayerInfo> players = KickBanTools.GetPlayers();
			int num = 0;
			foreach (KickBanTools.PlayerInfo item in players)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (item.Connected || item.SteamID != 0L)
				{
					GUILayout.Label($"({num}) {item}", item.IsPlayerDead ? LethalAdminUI.RedText : LethalAdminUI.WhiteText, LethalAdminUI.LabelOptions);
					GUILayout.Label($"Walkie: {item.WalkieMode}", LethalAdminUI.LabelOptions);
					if (num != 0 && GUILayout.Button("View info", Array.Empty<GUILayoutOption>()))
					{
						_banReason = "No reason given";
						_selectedPlayer = item;
					}
				}
				else
				{
					GUILayout.Label($"({num}) {item}", LethalAdminUI.YellowText, LethalAdminUI.LabelOptions);
				}
				GUILayout.EndHorizontal();
				num++;
			}
		}

		private static void DrawUserInfo()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if (GUILayout.Button("<- Back to users list", Array.Empty<GUILayoutOption>()))
			{
				_selectedPlayer = null;
				return;
			}
			GUILayout.Space(20f);
			GUILayout.Label($"User: {_selectedPlayer.Username} ({_selectedPlayer.SteamID}@steam)", Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Walkie talkie: {_selectedPlayer.WalkieMode}", Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			if (!_selectedPlayer.IsPlayerDead && GUILayout.Button("Kill player", Array.Empty<GUILayoutOption>()))
			{
				_selectedPlayer.PlayerController.DamagePlayerFromOtherClientServerRpc(10000, Vector3.zero, 0);
			}
			if (!_selectedPlayer.IsPlayerDead && GUILayout.Button("Teleport to player", Array.Empty<GUILayoutOption>()))
			{
				Round.localPlayerController.TeleportPlayer(((Component)_selectedPlayer.PlayerController).transform.position, false, 0f, false, true);
			}
			GUILayout.Space(20f);
			if (GUILayout.Button("Profile", Array.Empty<GUILayoutOption>()))
			{
				KickBanTools.ShowProfile(_selectedPlayer.Username, _selectedPlayer.SteamID);
			}
			if (BanHandler.IsWhitelisted(_selectedPlayer.SteamID))
			{
				if (GUILayout.Button("Remove from whitelist", Array.Empty<GUILayoutOption>()))
				{
					BanHandler.RemoveWhitelist(_selectedPlayer.SteamID);
				}
			}
			else if (GUILayout.Button("Add to whitelist", Array.Empty<GUILayoutOption>()))
			{
				BanHandler.AddWhitelist(_selectedPlayer.SteamID, _selectedPlayer.Username);
			}
			if (GUILayout.Button("Kick", Array.Empty<GUILayoutOption>()))
			{
				KickBanTools.KickPlayer(_selectedPlayer);
			}
			GUILayout.Space(5f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			_banReason = GUILayout.TextField(_banReason, LethalAdminUI.WideLabelOptions);
			if (GUILayout.Button("Ban", Array.Empty<GUILayoutOption>()))
			{
				KickBanTools.BanPlayer(_selectedPlayer, _banReason);
			}
			GUILayout.EndHorizontal();
		}
	}
	public class WhitelistView : IView
	{
		public string GetViewName()
		{
			return "Whitelist";
		}

		public void DrawView()
		{
			foreach (WhitelistInfo item in BanHandler.GetWhitelist())
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"{item.Username} ({item.SteamID}@steam)", LethalAdminUI.WideLabelOptions);
				if (GUILayout.Button("Steam profile", Array.Empty<GUILayoutOption>()))
				{
					KickBanTools.ShowProfile(item.Username, item.SteamID);
				}
				if (GUILayout.Button("Remove whitelist", Array.Empty<GUILayoutOption>()))
				{
					BanHandler.RemoveWhitelist(item.SteamID);
				}
				GUILayout.EndHorizontal();
			}
		}
	}
}
namespace LethalAdmin.Patches
{
	[HarmonyPatch(typeof(ShipBuildModeManager))]
	public class BuildingPatch
	{
		[HarmonyPatch("StoreObjectServerRpc")]
		[HarmonyPrefix]
		public static bool OnStoreObject(ShipBuildModeManager __instance, ref NetworkObjectReference objectRef, int playerWhoStored)
		{
			return OnBuild(__instance, ref objectRef, playerWhoStored, movingToStorage: true);
		}

		[HarmonyPatch("PlaceShipObjectServerRpc")]
		[HarmonyPrefix]
		public static bool OnPlacingObject(ShipBuildModeManager __instance, ref NetworkObjectReference objectRef, int playerWhoMoved)
		{
			return OnBuild(__instance, ref objectRef, playerWhoMoved, movingToStorage: false);
		}

		private static bool OnBuild(ShipBuildModeManager __instance, ref NetworkObjectReference objectRef, int playerId, bool movingToStorage)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (playerId == 0 || !Plugin.Instance.FurnitureLocked || !((NetworkBehaviour)__instance).IsServer)
			{
				return true;
			}
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			if (playerId < allPlayerScripts.Length && BanHandler.IsWhitelisted(allPlayerScripts[playerId].playerSteamId))
			{
				return true;
			}
			NetworkObject val = default(NetworkObject);
			if (!((NetworkObjectReference)(ref objectRef)).TryGet(ref val, (NetworkManager)null))
			{
				return false;
			}
			PlaceableShipObject componentInChildren = ((Component)val).GetComponentInChildren<PlaceableShipObject>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return false;
			}
			if (StartOfRound.Instance.unlockablesList.unlockables[componentInChildren.unlockableID].inStorage)
			{
				return false;
			}
			if (movingToStorage)
			{
				StartOfRound.Instance.ReturnUnlockableFromStorageClientRpc(componentInChildren.unlockableID);
			}
			else
			{
				Transform transform = ((Component)componentInChildren).transform;
				Vector3 position = transform.position;
				Quaternion rotation = ((Component)componentInChildren.mainMesh).transform.rotation;
				__instance.PlaceShipObjectClientRpc(position, ((Quaternion)(ref rotation)).eulerAngles, objectRef, 0);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	public class ConnectionPatch
	{
		public class RequestInformation
		{
			public bool IsDenied;

			public string DenyReason;
		}

		[HarmonyPatch("ConnectionApproval")]
		[HarmonyPriority(600)]
		[HarmonyPrefix]
		public static bool BanApproval(ref RequestInformation __state, ref ConnectionApprovalRequest request, ConnectionApprovalResponse response)
		{
			__state = new RequestInformation();
			if (request.ClientNetworkId == NetworkManager.Singleton.LocalClientId)
			{
				return false;
			}
			string[] array = Encoding.ASCII.GetString(request.Payload).Split(",");
			if (array.Length < 2)
			{
				if (!Plugin.Instance.RequireSteam || GameNetworkManager.Instance.disableSteam)
				{
					return true;
				}
				DeclineConnection(ref __state, response, "This lobby requires steam authentication.");
				return false;
			}
			ulong num;
			try
			{
				num = ulong.Parse(array[1]);
			}
			catch (Exception)
			{
				if (!Plugin.Instance.RequireSteam || GameNetworkManager.Instance.disableSteam)
				{
					return true;
				}
				DeclineConnection(ref __state, response, "This lobby requires steam authentication.");
				return false;
			}
			if (Plugin.Instance.RequireSteam && num == 0L)
			{
				DeclineConnection(ref __state, response, "This lobby requires steam authentication.");
				return false;
			}
			if (BanHandler.TryGetBan(num, out var banInfo))
			{
				DeclineConnection(ref __state, response, "<b>You are banned from this lobby:</b>\n" + banInfo.BanReason);
				return false;
			}
			return true;
		}

		[HarmonyPatch("ConnectionApproval")]
		[HarmonyPriority(0)]
		[HarmonyPostfix]
		public static void AfterApproval(ref RequestInformation __state, ConnectionApprovalResponse response)
		{
			if (__state != null && __state.IsDenied && response.Approved)
			{
				DeclineConnection(ref __state, response, __state.DenyReason);
			}
		}

		private static void DeclineConnection(ref RequestInformation state, ConnectionApprovalResponse response, string reason)
		{
			state.IsDenied = true;
			state.DenyReason = reason;
			response.Reason = reason;
			response.CreatePlayerObject = false;
			response.Approved = false;
			response.Pending = false;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public class ControllerPatch
	{
		[HarmonyPatch("ConnectClientToPlayerObject")]
		[HarmonyPostfix]
		public static void OnPlayerJoin(PlayerControllerB __instance)
		{
			LethalLogger.AddLog(new Log($"[Connect] {__instance.playerUsername} ({__instance.playerSteamId}@steam) has joined"));
			if (__instance.playerSteamId == 0L && Plugin.Instance.RequireSteam && !GameNetworkManager.Instance.disableSteam)
			{
				KickBanTools.KickPlayer(new KickBanTools.PlayerInfo
				{
					Username = __instance.playerUsername,
					SteamID = __instance.playerSteamId,
					Connected = true,
					IsPlayerDead = __instance.isPlayerDead
				});
			}
		}
	}
	[HarmonyPatch(typeof(QuickMenuManager))]
	public class MenuPatch
	{
		[HarmonyPatch("OpenQuickMenu")]
		[HarmonyPostfix]
		public static void OnOpenMenu()
		{
			LethalAdminUI.SetMenuForAll(value: true);
		}

		[HarmonyPatch("CloseQuickMenu")]
		[HarmonyPostfix]
		public static void OnCloseMenu()
		{
			LethalAdminUI.SetMenuForAll(value: false);
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public static class RoundPatch
	{
		[HarmonyPatch("KickPlayer")]
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void OnKick()
		{
			KickBanTools.UpdateKickedIDs();
		}

		[HarmonyPatch("EndGameClientRpc")]
		[HarmonyPostfix]
		public static void OnShipLeave(StartOfRound __instance, int playerClientId)
		{
			if (playerClientId < __instance.allPlayerScripts.Length)
			{
				PlayerControllerB val = __instance.allPlayerScripts[playerClientId];
				LethalLogger.AddLog(new Log($"[Departure] {val.playerUsername} ({val.playerSteamId}@steam) has started the ship"));
			}
		}

		[HarmonyPatch("StartGameServerRpc")]
		[HarmonyPrefix]
		public static bool NonServerStartGame(StartOfRound __instance)
		{
			if (!Plugin.Instance.LockLever || !((NetworkBehaviour)__instance).IsServer)
			{
				return true;
			}
			LethalLogger.AddLog(new Log("[Start Game] Blocked bypass attempt on " + (((NetworkBehaviour)__instance).IsServer ? "Server" : "Client")));
			StartMatchLever obj = Object.FindObjectOfType<StartMatchLever>();
			obj.CancelStartGameClientRpc();
			obj.triggerScript.interactable = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(TimeOfDay))]
	public class VotingPatch
	{
		[HarmonyPatch("SetShipLeaveEarlyServerRpc")]
		[HarmonyPrefix]
		public static bool OnServerVote(TimeOfDay __instance)
		{
			if (Plugin.Instance.MinVotes <= 1 || !((NetworkBehaviour)__instance).IsServer)
			{
				return true;
			}
			if (__instance.votesForShipToLeaveEarly + 1 >= Plugin.Instance.MinVotes)
			{
				return true;
			}
			__instance.votesForShipToLeaveEarly++;
			__instance.AddVoteForShipToLeaveEarlyClientRpc();
			return false;
		}
	}
}
namespace LethalAdmin.Logging
{
	public static class LethalLogger
	{
		private const int MaxLogCount = 50;

		private static readonly List<Log> Logs = new List<Log>();

		public static void AddLog(Log log)
		{
			Logs.Add(log);
			while (Logs.Count > 50)
			{
				Logs.RemoveAt(0);
			}
		}

		public static IEnumerable<Log> GetLogs()
		{
			return Logs.ToArray();
		}
	}
	public class Log
	{
		private readonly string _prefix;

		private readonly float _time = Time.realtimeSinceStartup;

		private readonly string _message;

		public Log(string message, string prefix = "Info")
		{
			_message = message;
			_prefix = prefix;
		}

		public string GetTimeFormattedString()
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(_time);
			return $"[{timeSpan:hh':'mm':'ss}] [{_prefix}] {_message}";
		}
	}
}
namespace LethalAdmin.Bans
{
	public static class BanHandler
	{
		private static readonly Dictionary<ulong, BanInfo> Bans = new Dictionary<ulong, BanInfo>();

		private static readonly Dictionary<ulong, WhitelistInfo> Whitelist = new Dictionary<ulong, WhitelistInfo>();

		public static void LoadBans()
		{
			string path = Path.Combine(Plugin.ConfigFolder, "gamendegamer.lethaladmin.json");
			if (!File.Exists(path))
			{
				return;
			}
			BanList banList = JsonConvert.DeserializeObject<BanList>(File.ReadAllText(path));
			if (banList == null)
			{
				LethalLogger.AddLog(new Log("[Ban Handler] Failed to load ban list"));
				return;
			}
			foreach (BanInfo ban in banList.Bans)
			{
				Bans.Add(ban.SteamID, ban);
			}
			foreach (WhitelistInfo item in banList.Whitelist)
			{
				Whitelist.Add(item.SteamID, item);
			}
			KickBanTools.UpdateKickedIDs();
		}

		public static void LoadDeprecated(string[] deprecatedBans)
		{
			if (deprecatedBans.Length == 0)
			{
				return;
			}
			for (int i = 0; i < deprecatedBans.Length; i++)
			{
				if (ulong.TryParse(deprecatedBans[i], out var result))
				{
					Bans.Add(result, new BanInfo
					{
						SteamID = result
					});
				}
			}
			KickBanTools.UpdateKickedIDs();
			SaveBans();
		}

		public static bool AddWhitelist(ulong id, string username)
		{
			if (Whitelist.ContainsKey(id))
			{
				return false;
			}
			Whitelist.Add(id, new WhitelistInfo
			{
				SteamID = id,
				Username = username
			});
			SaveBans();
			return true;
		}

		public static bool RemoveWhitelist(ulong id)
		{
			if (!Whitelist.ContainsKey(id))
			{
				return false;
			}
			Whitelist.Remove(id);
			SaveBans();
			return true;
		}

		public static bool AddBan(ulong id, string username, string reason)
		{
			if (Bans.ContainsKey(id))
			{
				return false;
			}
			if ((reason == null || reason == "") ? true : false)
			{
				reason = "No reason given";
			}
			Bans.Add(id, new BanInfo
			{
				SteamID = id,
				Username = username,
				BanReason = reason
			});
			SaveBans();
			return true;
		}

		public static bool RemoveBan(ulong id)
		{
			if (!Bans.ContainsKey(id))
			{
				return false;
			}
			Bans.Remove(id);
			SaveBans();
			return true;
		}

		public static IEnumerable<BanInfo> GetBans()
		{
			return Bans.Values;
		}

		public static IEnumerable<WhitelistInfo> GetWhitelist()
		{
			return Whitelist.Values;
		}

		public static bool TryGetBan(ulong id, out BanInfo banInfo)
		{
			return Bans.TryGetValue(id, out banInfo);
		}

		public static bool IsWhitelisted(ulong id)
		{
			return Whitelist.Keys.Contains(id);
		}

		private static void SaveBans()
		{
			string path = Path.Combine(Plugin.ConfigFolder, "gamendegamer.lethaladmin.json");
			string contents = JsonConvert.SerializeObject((object)new BanList
			{
				Bans = Bans.Values.ToList(),
				Whitelist = Whitelist.Values.ToList()
			});
			File.WriteAllText(path, contents);
		}
	}
	public class BanInfo
	{
		public ulong SteamID;

		public string Username = "UNKNOWN";

		public string BanReason = "None given";
	}
	public class BanList
	{
		public List<BanInfo> Bans;

		public List<WhitelistInfo> Whitelist;
	}
	public class WhitelistInfo
	{
		public ulong SteamID;

		public string Username;
	}
}