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;
}
}