Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Lethal Admin v1.10.0
LethalAdmin.dll
Decompiled 8 months agousing 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 Steamworks.Data; 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+47e6036f8852e0b3ead929338e875c4caa393a91")] [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 enum ConnectionState { Disconnected, Connected, OnlySteamConnected } public static class ConnectionTracker { internal static readonly List<SteamId> SteamIds = new List<SteamId>(); internal static readonly Dictionary<ulong, ulong> SteamIdsToNetworkIds = new Dictionary<ulong, ulong>(); public static void RegisterEvents() { SteamMatchmaking.OnLobbyMemberJoined += OnJoinedLobby; SteamMatchmaking.OnLobbyMemberLeave += OnLeftLobby; } private static void OnJoinedLobby(Lobby lobby, Friend friend) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) LethalLogger.AddLog(new Log($"Friend joined with steamID: {friend.Id}")); SteamIds.Clear(); SteamIds.AddRange(((Lobby)(ref lobby)).Members.Select((Friend x) => x.Id)); List<ulong> list = new List<ulong>(); foreach (ulong id in SteamIdsToNetworkIds.Keys) { if (SteamIds.All((SteamId x) => x.Value != id)) { list.Add(id); } } foreach (ulong item in list) { SteamIdsToNetworkIds.Remove(item); } } private static void OnLeftLobby(Lobby lobby, Friend friend) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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) //IL_003b: Unknown result type (might be due to invalid IL or missing references) LethalLogger.AddLog(new Log($"Friend left with steamID: {friend.Id}")); SteamIds.Remove(friend.Id); SteamIdsToNetworkIds.Remove(SteamId.op_Implicit(friend.Id)); } } public static class KickBanTools { public class PlayerInfo { public string Username; public ulong SteamID; public ConnectionState ConnectionState; 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() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; List<PlayerInfo> result = allPlayerScripts.Select((PlayerControllerB player, int i) => new PlayerInfo { Username = player.playerUsername, SteamID = player.playerSteamId, ConnectionState = (StartOfRound.Instance.fullyLoadedPlayers.Contains((ulong)i) ? ConnectionState.Connected : ConnectionState.Disconnected), WalkieMode = GetWalkieMode(player), IsPlayerDead = player.isPlayerDead, PlayerController = player }).ToList(); foreach (SteamId item in ConnectionTracker.SteamIds.Where((SteamId x) => result.All((PlayerInfo y) => x.Value != y.SteamID))) { result.Add(new PlayerInfo { Username = "Player without script", SteamID = SteamId.op_Implicit(item), ConnectionState = (ConnectionTracker.SteamIdsToNetworkIds.ContainsKey(item.Value) ? ConnectionState.OnlySteamConnected : ConnectionState.Disconnected), WalkieMode = WalkieMode.Disabled, IsPlayerDead = false }); } return result; } 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; bool flag = false; for (int i = 0; i < allPlayerScripts.Length; i++) { if (allPlayerScripts[i].playerSteamId == playerInfo.SteamID) { StartOfRound.Instance.KickPlayer(i); LethalLogger.AddLog(new Log($"[Kick] {playerInfo} has been kicked (id={i})")); flag = true; } } if (flag || playerInfo.SteamID == 0L || !Plugin.Instance.SteamChecker) { return; } LethalLogger.AddLog(new Log($"[Kick] {playerInfo} could not be kicked, no matching player controller")); if (playerInfo.ConnectionState == ConnectionState.OnlySteamConnected) { if (ConnectionTracker.SteamIdsToNetworkIds.TryGetValue(playerInfo.SteamID, out var value)) { LethalLogger.AddLog(new Log($"[Kick] Only a steam connection found, attempting to force stop the connection! (con. id={value})")); NetworkManager.Singleton.DisconnectClient(value); } else { LethalLogger.AddLog(new Log("[Kick] Could not find the connection associated with the steam ID, kicking is not possible for this user!")); } } } 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.10.0")] public class Plugin : BaseUnityPlugin { public const string PluginVersion = "1.10.0"; 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; private ConfigEntry<bool> _steamChecker; 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(); } } public bool SteamChecker { get { return _steamChecker.Value; } set { _steamChecker.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."); _steamChecker = ((BaseUnityPlugin)this).Config.Bind<bool>("Lethal Admin", "steamChecker", true, "When enabled will do an additional attempt to kick a player"); 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(); } ConnectionTracker.RegisterEvents(); ((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.10.0", _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("Log debug information", Array.Empty<GUILayoutOption>())) { LethalLogger.AddLog(new Log($"disableSteam: {GameNetworkManager.Instance.disableSteam}, transport: {(Object)(object)GameNetworkManager.Instance.transport != (Object)null}")); } 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 bool _steamChecker = Plugin.Instance.SteamChecker; 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>()); _steamChecker = GUILayout.Toggle(_steamChecker, "[Experimental] Additional kick attempt", 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; Plugin.Instance.SteamChecker = _steamChecker; _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.ConnectionState != 0 || 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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.ConnectionState == ConnectionState.Connected && !_selectedPlayer.IsPlayerDead && GUILayout.Button("Kill player", Array.Empty<GUILayoutOption>())) { _selectedPlayer.PlayerController.DamagePlayerFromOtherClientServerRpc(10000, Vector3.zero, 0); } if (_selectedPlayer.ConnectionState == ConnectionState.Connected && !_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 steamId; try { steamId = 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 && steamId == 0L) { DeclineConnection(ref __state, response, "This lobby requires steam authentication."); return false; } if (Plugin.Instance.RequireSteam && Plugin.Instance.SteamChecker && ConnectionTracker.SteamIds.All((SteamId x) => x.Value != steamId)) { LethalLogger.AddLog(new Log($"[Connect] Connection request for steamId {steamId} denied")); DeclineConnection(ref __state, response, "This lobby requires steam authentication."); return false; } if (BanHandler.TryGetBan(steamId, out var banInfo)) { DeclineConnection(ref __state, response, "<b>You are banned from this lobby:</b>\n" + banInfo.BanReason); return false; } ConnectionTracker.SteamIdsToNetworkIds[steamId] = request.ClientNetworkId; 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); } } [HarmonyPatch("StartHost")] [HarmonyPrefix] public static void StartHost() { ConnectionTracker.SteamIds.Clear(); ConnectionTracker.SteamIdsToNetworkIds.Clear(); } 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, ConnectionState = ConnectionState.Connected, 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>(); private static ManualLogSource LogSource = Logger.CreateLogSource("LethalLogger"); public static void AddLog(Log log) { Logs.Add(log); LogSource.LogInfo((object)log.GetTimeFormattedString()); 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; } }