Please disclose if any significant portion of your mod was created 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 ModMenu v0.1.0
ModMenu.dll
Decompiled 3 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.UI; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("ModMenuTest")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ModMenu")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+e03db308db5b2f5b1076eb9e188f6be649e3cbc4")] [assembly: AssemblyProduct("ModMenu")] [assembly: AssemblyTitle("ModMenu")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ModMenu { internal class Menu : MonoBehaviour { internal class Row { public MenuApi.Entry Entry; public string Heading; public string Blocked; } internal static Menu Instance; internal string Tab; internal string Search = ""; internal int Cursor; internal int Scroll; internal readonly List<Row> Rows = new List<Row>(); internal const string FavTab = "Favourites"; internal const int VisibleRows = 8; private Panel _panel; private int _builtVersion = -1; private float _nextRefresh; internal bool IsOpen { get; private set; } internal static PlayerControllerB Me { get { if (!((Object)(object)GameNetworkManager.Instance != (Object)null)) { return null; } return GameNetworkManager.Instance.localPlayerController; } } private void Awake() { Instance = this; } internal static string CannotOpen() { PlayerControllerB me = Me; if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)me == (Object)null) { return "not in a game"; } if (!me.isPlayerControlled || me.isPlayerDead) { return "not while dead"; } if (me.inTerminalMenu) { return "not at the terminal"; } if (me.isTypingChat) { return "not while typing"; } if (me.inSpecialMenu) { return "not in another menu"; } if ((Object)(object)me.quickMenuManager == (Object)null || me.quickMenuManager.isMenuOpen) { return "not in the pause menu"; } return null; } internal void Toggle() { if (IsOpen) { Close(); } else { Open(); } } internal bool Open() { if (IsOpen) { return true; } string text = CannotOpen(); if (text != null) { Plugin.Log.LogInfo((object)("ModMenu: can't open (" + text + ").")); return false; } if ((Object)(object)_panel == (Object)null) { _panel = Panel.Create(this); } Me.quickMenuManager.isMenuOpen = true; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; if (Keyboard.current != null) { Keyboard.current.onTextInput += OnText; } IsOpen = true; List<string> list = TabList(); Tab = (list.Contains(Plugin.LastTab.Value) ? Plugin.LastTab.Value : list.FirstOrDefault()); Search = ""; Cursor = 0; Scroll = 0; Rebuild(); ((Component)_panel).gameObject.SetActive(true); return true; } internal void Close(bool quickMenuClosed = false) { if (IsOpen) { IsOpen = false; if (Keyboard.current != null) { Keyboard.current.onTextInput -= OnText; } if ((Object)(object)_panel != (Object)null) { ((Component)_panel).gameObject.SetActive(false); } PlayerControllerB me = Me; if (!quickMenuClosed && (Object)(object)me != (Object)null && (Object)(object)me.quickMenuManager != (Object)null && !me.quickMenuManager.menuContainer.activeSelf) { me.quickMenuManager.isMenuOpen = false; Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } if (Tab != null) { Plugin.LastTab.Value = Tab; } } } private void Update() { //IL_0133: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return; } PlayerControllerB me = Me; if ((Object)(object)me == (Object)null || (Object)(object)me.quickMenuManager == (Object)null || !me.quickMenuManager.isMenuOpen) { Close(quickMenuClosed: true); return; } if (me.isPlayerDead || !me.isPlayerControlled || me.inTerminalMenu) { Close(); return; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; Keyboard current = Keyboard.current; if (current != null) { if (((ButtonControl)current.upArrowKey).wasPressedThisFrame) { Move(-1); } if (((ButtonControl)current.downArrowKey).wasPressedThisFrame) { Move(1); } if (((ButtonControl)current.leftArrowKey).wasPressedThisFrame) { StepTab(-1); } if (((ButtonControl)current.rightArrowKey).wasPressedThisFrame) { StepTab(1); } if (((ButtonControl)current.enterKey).wasPressedThisFrame || ((ButtonControl)current.numpadEnterKey).wasPressedThisFrame) { RunRow(Cursor); } if (((ButtonControl)current.backspaceKey).wasPressedThisFrame && Search.Length > 0) { SetSearch(Search.Substring(0, Search.Length - 1)); } } Mouse current2 = Mouse.current; if (current2 != null) { float y = ((InputControl<Vector2>)(object)current2.scroll).ReadValue().y; if (y != 0f) { Scroll = Mathf.Clamp(Scroll + ((!(y > 0f)) ? 1 : (-1)), 0, Mathf.Max(0, Rows.Count - 8)); _panel.Redraw(); } } if (_builtVersion != MenuApi.Version) { Rebuild(); } else if (Time.unscaledTime >= _nextRefresh) { _nextRefresh = Time.unscaledTime + 0.25f; RefreshBlocked(); _panel.Redraw(); } } private void OnText(char c) { if (IsOpen && !char.IsControl(c) && Search.Length < 24) { SetSearch(Search + c); } } internal List<string> TabList() { List<string> list = new List<string>(); HashSet<string> fav = Plugin.Favourites; if (Shown().Any((MenuApi.Entry e) => fav.Contains(e.Key))) { list.Add("Favourites"); } list.AddRange(MenuApi.Tabs.Where((string t) => Shown().Any((MenuApi.Entry e) => e.Tab == t))); return list; } private static IEnumerable<MenuApi.Entry> Shown() { return MenuApi.Entries.Where((MenuApi.Entry e) => !e.Cheat || Plugin.CheatsEnabled.Value); } internal void Rebuild() { _builtVersion = MenuApi.Version; Rows.Clear(); List<string> list = TabList(); if (Search.Length > 0) { string s = Search.ToLowerInvariant(); foreach (string t in MenuApi.Tabs) { List<MenuApi.Entry> list2 = (from e in Shown() where e.Tab == t && (e.Label.ToLowerInvariant().Contains(s) || t.ToLowerInvariant().Contains(s)) select e).ToList(); if (list2.Count != 0) { Rows.Add(new Row { Heading = t }); Rows.AddRange(list2.Select((MenuApi.Entry e) => new Row { Entry = e })); } } } else { if (Tab == null || !list.Contains(Tab)) { Tab = list.FirstOrDefault(); } HashSet<string> fav = Plugin.Favourites; IEnumerable<MenuApi.Entry> source = ((Tab == "Favourites") ? (from e in Shown() where fav.Contains(e.Key) select e) : (from e in Shown() where e.Tab == Tab select e)); Rows.AddRange(source.Select((MenuApi.Entry e) => new Row { Entry = e })); } RefreshBlocked(); Cursor = Mathf.Clamp(Cursor, 0, Mathf.Max(0, Rows.Count - 1)); if (Rows.Count > 0 && Rows[Cursor].Entry == null) { Cursor = Math.Min(Cursor + 1, Rows.Count - 1); } KeepCursorVisible(); _panel?.Redraw(); } internal void RefreshBlocked() { bool flag = (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsHost; foreach (Row row in Rows) { if (row.Entry == null) { continue; } string blocked = null; if (row.Entry.Host && !flag) { blocked = "host only"; } else if (row.Entry.Unavailable != null) { try { blocked = row.Entry.Unavailable(); } catch (Exception ex) { blocked = "error"; Plugin.Log.LogWarning((object)("ModMenu: " + row.Entry.Key + " check failed: " + ex.Message)); } } row.Blocked = blocked; } } internal void SetSearch(string s) { Search = s; Cursor = 0; Scroll = 0; Rebuild(); } internal void SelectTab(string t) { Tab = t; Search = ""; Cursor = 0; Scroll = 0; Plugin.LastTab.Value = t; Rebuild(); } private void StepTab(int d) { List<string> list = TabList(); if (list.Count != 0) { int num = ((Search.Length <= 0) ? Math.Max(0, list.IndexOf(Tab)) : 0); SelectTab(list[(num + d + list.Count) % list.Count]); } } private void Move(int d) { if (Rows.Count == 0) { return; } int num = Cursor; for (int i = 0; i < Rows.Count; i++) { num = (num + d + Rows.Count) % Rows.Count; if (Rows[num].Entry != null) { break; } } Cursor = num; KeepCursorVisible(); _panel.Redraw(); } private void KeepCursorVisible() { if (Cursor < Scroll) { Scroll = ((Cursor > 0 && Rows[Cursor - 1].Entry == null) ? (Cursor - 1) : Cursor); } if (Cursor >= Scroll + 8) { Scroll = Cursor - 8 + 1; } Scroll = Mathf.Clamp(Scroll, 0, Mathf.Max(0, Rows.Count - 8)); } internal void ToggleFavourite(int row) { if (row >= 0 && row < Rows.Count && Rows[row].Entry != null) { MenuApi.Entry entry = Rows[row].Entry; Plugin.SetFavourite(entry.Key, !Plugin.Favourites.Contains(entry.Key)); Rebuild(); } } internal string RunRow(int row) { if (row < 0 || row >= Rows.Count || Rows[row].Entry == null) { return null; } Cursor = row; RefreshBlocked(); Row row2 = Rows[row]; MenuApi.Entry entry = row2.Entry; if (row2.Blocked != null) { Tip(entry.Tab, entry.Label + ": " + row2.Blocked + "."); _panel?.Redraw(); return null; } string text; try { text = (entry.IsToggle ? entry.Set(!entry.Get()) : entry.Run()); } catch (Exception arg) { Plugin.Log.LogError((object)$"ModMenu: {entry.Key} failed: {arg}"); Tip(entry.Tab, entry.Label + " failed (see the log)."); return null; } Plugin.Log.LogInfo((object)("ModMenu: " + entry.Key + " -> " + (text ?? "(nothing)"))); if (text != null) { Tip(entry.Tab, Capital(text) + "."); if (entry.Cheat && Plugin.Announce.Value) { AnnounceCheat(text); } } RefreshBlocked(); _panel?.Redraw(); return text; } internal static void AnnounceCheat(string result) { HUDManager instance = HUDManager.Instance; PlayerControllerB me = Me; if ((Object)(object)instance == (Object)null || (Object)(object)me == (Object)null) { return; } try { instance.AddTextToChatOnServer("<color=#9a9a9a>" + me.playerUsername + " " + result + " [Mod Menu]</color>", -1); } catch (Exception ex) { Plugin.Log.LogWarning((object)("ModMenu: chat announce failed: " + ex.Message)); } } internal static void Tip(string title, string body) { try { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip(title, body, false, false, "LC_Tip1"); } } catch { } } private static string Capital(string s) { if (!string.IsNullOrEmpty(s)) { return char.ToUpperInvariant(s[0]) + s.Substring(1); } return s; } } public static class MenuApi { internal class Entry { public string Tab; public string Label; public string Note; public Func<string> Run; public Func<bool> Get; public Func<bool, string> Set; public Func<string> Unavailable; public bool Host; public bool Cheat; public bool IsToggle => Get != null; public string Key => Tab + "/" + Label; } internal static readonly List<Entry> Entries = new List<Entry>(); internal static readonly List<string> Tabs = new List<string>(); internal static int Version; public static void Button(string tab, string label, Func<string> run, bool host = false, bool cheat = false, Func<string> unavailable = null, string note = null) { Add(new Entry { Tab = tab, Label = label, Run = run, Host = host, Cheat = cheat, Unavailable = unavailable, Note = note }); } public static void Toggle(string tab, string label, Func<bool> get, Func<bool, string> set, bool host = false, bool cheat = false, Func<string> unavailable = null, string note = null) { Add(new Entry { Tab = tab, Label = label, Get = get, Set = set, Host = host, Cheat = cheat, Unavailable = unavailable, Note = note }); } public static void Choice(string tab, string label, string[] options, Func<int, string> run, bool host = false, bool cheat = false, Func<string> unavailable = null, string note = null) { for (int i = 0; i < options.Length; i++) { int k = i; Add(new Entry { Tab = tab, Label = label + ": " + options[i], Run = () => run(k), Host = host, Cheat = cheat, Unavailable = unavailable, Note = note }); } } public static void ClearTab(string tab) { Entries.RemoveAll((Entry e) => e.Tab == tab); Tabs.RemoveAll((string t) => t == tab); Version++; } private static void Add(Entry e) { if (string.IsNullOrEmpty(e.Tab) || string.IsNullOrEmpty(e.Label)) { throw new ArgumentException("ModMenu: tab and label are required."); } Entries.RemoveAll((Entry x) => x.Key == e.Key); Entries.Add(e); if (!Tabs.Contains(e.Tab)) { Tabs.Add(e.Tab); } Version++; ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("ModMenu: registered " + e.Key)); } } } internal class Panel : MonoBehaviour { private class RowUi { public GameObject Go; public Image Bg; public TextMeshProUGUI Star; public TextMeshProUGUI Label; public TextMeshProUGUI Note; public TextMeshProUGUI Act; public TextMeshProUGUI Heading; } private static readonly Color Green = Color32.op_Implicit(new Color32((byte)60, byte.MaxValue, (byte)90, byte.MaxValue)); private static readonly Color Dim = Color32.op_Implicit(new Color32((byte)40, (byte)150, (byte)60, byte.MaxValue)); private static readonly Color Orange = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)140, (byte)30, byte.MaxValue)); private static readonly Color Grey = Color32.op_Implicit(new Color32((byte)115, (byte)125, (byte)115, byte.MaxValue)); private static readonly Color Back = Color32.op_Implicit(new Color32((byte)6, (byte)14, (byte)8, (byte)240)); private static readonly Color RowBack = Color32.op_Implicit(new Color32((byte)12, (byte)30, (byte)16, byte.MaxValue)); private static readonly Color RowSel = Color32.op_Implicit(new Color32((byte)30, (byte)90, (byte)40, byte.MaxValue)); private static readonly Color Line = Color32.op_Implicit(new Color32((byte)30, (byte)80, (byte)40, byte.MaxValue)); private const float W = 1200f; private const float H = 760f; private const float TabW = 260f; private const float RowH = 64f; private const float Pad = 24f; private const int MaxTabs = 12; private Menu _menu; private TMP_FontAsset _font; private TextMeshProUGUI _search; private TextMeshProUGUI _footer; private TextMeshProUGUI _heading; private readonly List<(Image bg, TextMeshProUGUI text)> _tabs = new List<(Image, TextMeshProUGUI)>(); private readonly List<RowUi> _rows = new List<RowUi>(); internal static Panel Create(Menu menu) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ModMenu.Canvas"); Object.DontDestroyOnLoad((Object)(object)val); Canvas obj = val.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 900; CanvasScaler obj2 = val.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; val.AddComponent<GraphicRaycaster>(); Panel panel = val.AddComponent<Panel>(); panel._menu = menu; panel.Build(); val.SetActive(false); return panel; } private TMP_FontAsset FindFont() { Terminal val = Object.FindObjectOfType<Terminal>(); if ((Object)(object)val != (Object)null && (Object)(object)val.screenText != (Object)null && (Object)(object)val.screenText.textComponent != (Object)null) { return val.screenText.textComponent.font; } if ((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.chatText != (Object)null) { return ((TMP_Text)HUDManager.Instance.chatText).font; } return TMP_Settings.defaultFontAsset; } private void Build() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) //IL_04b8: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_054b: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Unknown result type (might be due to invalid IL or missing references) _font = FindFont(); EnsureEventSystem(); RectTransform val = Rect("Box", ((Component)this).transform, new Vector2(1200f, 760f), Vector2.zero); Img((Transform)(object)val, Back); Outline((Transform)(object)val, Green, 2f); Text((Transform)(object)val, "MOD MENU", 34f, Orange, new Vector2(24f, -24f), new Vector2(400f, 44f), (FontStyles)1); TextMeshProUGUI obj = Text((Transform)(object)val, "", 20f, Dim, new Vector2(816f, -32f), new Vector2(360f, 30f), (FontStyles)0); ((TMP_Text)obj).alignment = (TextAlignmentOptions)516; ((Object)((Component)obj).gameObject).name = "CloseHint"; RectTransform val2 = Rect("SearchBox", (Transform)(object)val, new Vector2(1152f, 40f), new Vector2(24f, -80f), topLeft: true); Outline((Transform)(object)val2, Dim, 1f); _search = Text((Transform)(object)val2, "", 22f, Green, new Vector2(12f, -6f), new Vector2(1128f, 30f), (FontStyles)0); for (int i = 0; i < 12; i++) { int k = i; RectTransform val3 = Rect("Tab" + i, (Transform)(object)val, new Vector2(250f, 42f), new Vector2(24f, (float)(-140 - i * 46)), topLeft: true); Image item = Img((Transform)(object)val3, new Color(0f, 0f, 0f, 0f)); TextMeshProUGUI item2 = Text((Transform)(object)val3, "", 22f, Dim, new Vector2(12f, -8f), new Vector2(230f, 30f), (FontStyles)0); Click((Transform)(object)val3, delegate { OnTab(k); }); _tabs.Add((item, item2)); } Img((Transform)(object)Rect("Divider", (Transform)(object)val, new Vector2(1f, 560f), new Vector2(288f, -136f), topLeft: true), Dim); float num = 312f; float num2 = 1200f - num - 24f; _heading = Text((Transform)(object)val, "", 24f, Orange, new Vector2(num, -140f), new Vector2(num2, 32f), (FontStyles)1); for (int num3 = 0; num3 < 8; num3++) { int k2 = num3; RowUi rowUi = new RowUi(); RectTransform val4 = Rect("Row" + num3, (Transform)(object)val, new Vector2(num2, 56f), new Vector2(num, -180f - (float)num3 * 64f), topLeft: true); rowUi.Go = ((Component)val4).gameObject; rowUi.Bg = Img((Transform)(object)val4, RowBack); Outline((Transform)(object)val4, Line, 1f); rowUi.Heading = Text((Transform)(object)val4, "", 20f, Orange, new Vector2(4f, -18f), new Vector2(num2 - 8f, 28f), (FontStyles)1); RectTransform val5 = Rect("Star", (Transform)(object)val4, new Vector2(40f, 56f), new Vector2(0f, 0f), topLeft: true); Img((Transform)(object)val5, new Color(0f, 0f, 0f, 0f)); rowUi.Star = Text((Transform)(object)val5, "", 26f, Dim, new Vector2(10f, -10f), new Vector2(30f, 34f), (FontStyles)0); Click((Transform)(object)val5, delegate { _menu.ToggleFavourite(_menu.Scroll + k2); }); rowUi.Label = Text((Transform)(object)val4, "", 24f, Green, new Vector2(48f, -4f), new Vector2(num2 - 260f, 30f), (FontStyles)0); rowUi.Note = Text((Transform)(object)val4, "", 16f, Dim, new Vector2(48f, -32f), new Vector2(num2 - 260f, 22f), (FontStyles)0); rowUi.Act = Text((Transform)(object)val4, "", 24f, Green, new Vector2(num2 - 200f, -14f), new Vector2(180f, 30f), (FontStyles)1); ((TMP_Text)rowUi.Act).alignment = (TextAlignmentOptions)516; Click((Transform)(object)val4, delegate { _menu.RunRow(_menu.Scroll + k2); }); ((Transform)val5).SetAsLastSibling(); _rows.Add(rowUi); } _footer = Text((Transform)(object)val, "", 18f, Dim, new Vector2(24f, -716f), new Vector2(1152f, 26f), (FontStyles)0); } private void OnTab(int i) { List<string> list = _menu.TabList(); if (i < list.Count) { _menu.SelectTab(list[i]); } } internal void Redraw() { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_font == (Object)null)) { string name = ((Object)_font).name; TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset; if (!(name == ((defaultFontAsset != null) ? ((Object)defaultFontAsset).name : null))) { goto IL_005a; } } TMP_FontAsset val = FindFont(); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_font) { SetFont(val); } goto IL_005a; IL_005a: List<string> list = _menu.TabList(); bool flag = _menu.Search.Length > 0; for (int i = 0; i < _tabs.Count; i++) { (Image bg, TextMeshProUGUI text) tuple = _tabs[i]; Image item = tuple.bg; TextMeshProUGUI item2 = tuple.text; bool flag2 = i < list.Count; ((Component)item).gameObject.SetActive(flag2); if (flag2) { bool flag3 = !flag && list[i] == _menu.Tab; ((TMP_Text)item2).text = list[i]; ((Graphic)item2).color = (flag3 ? Green : Dim); ((TMP_Text)item2).fontStyle = (FontStyles)(flag3 ? 1 : 0); ((Graphic)item).color = (Color)(flag3 ? RowSel : new Color(0f, 0f, 0f, 0f)); } } ((TMP_Text)_search).text = (flag ? ("Search: " + _menu.Search + "_") : "<color=#2a7a3a>Type to search</color>"); ((TMP_Text)_heading).text = (flag ? $"{Count()} MATCHES" : (_menu.Tab ?? "No mods registered").ToUpperInvariant()); ((TMP_Text)((Component)((Component)this).transform.Find("Box/CloseHint")).GetComponent<TextMeshProUGUI>()).text = Keys.Shown + " / Esc to close"; HashSet<string> favourites = Plugin.Favourites; for (int j = 0; j < _rows.Count; j++) { RowUi rowUi = _rows[j]; int num = _menu.Scroll + j; if (num >= _menu.Rows.Count) { rowUi.Go.SetActive(false); continue; } rowUi.Go.SetActive(true); Menu.Row row = _menu.Rows[num]; bool flag4 = row.Entry == null; ((Component)rowUi.Heading).gameObject.SetActive(flag4); ((Component)((TMP_Text)rowUi.Star).transform.parent).gameObject.SetActive(!flag4); ((Component)rowUi.Label).gameObject.SetActive(!flag4); ((Component)rowUi.Note).gameObject.SetActive(!flag4); ((Component)rowUi.Act).gameObject.SetActive(!flag4); ((Graphic)rowUi.Bg).color = (Color)(flag4 ? new Color(0f, 0f, 0f, 0f) : ((num == _menu.Cursor) ? RowSel : RowBack)); if (flag4) { ((TMP_Text)rowUi.Heading).text = row.Heading.ToUpperInvariant(); continue; } MenuApi.Entry entry = row.Entry; bool flag5 = row.Blocked == null; bool flag6 = favourites.Contains(entry.Key); ((TMP_Text)rowUi.Star).text = (flag6 ? G('★', "*") : G('☆', "+")); ((Graphic)rowUi.Star).color = (flag6 ? Orange : Dim); ((TMP_Text)rowUi.Label).text = entry.Label; ((Graphic)rowUi.Label).color = (flag5 ? Green : Grey); List<string> list2 = new List<string>(); if (row.Blocked != null) { list2.Add(row.Blocked); } else { if (entry.Host) { list2.Add("host"); } if (entry.Cheat) { list2.Add("cheat"); } } if (entry.Note != null) { list2.Add(entry.Note); } ((TMP_Text)rowUi.Note).text = string.Join(" · ", list2); ((Graphic)rowUi.Note).color = (flag5 ? Dim : Grey); ((TMP_Text)rowUi.Act).text = ((!entry.IsToggle) ? "[ RUN ]" : (SafeGet(entry) ? "[ ON ]" : "[ OFF ]")); ((Graphic)rowUi.Act).color = ((!flag5) ? Grey : ((entry.IsToggle && SafeGet(entry)) ? Orange : Green)); } string text = ((_menu.Rows.Count > 8) ? $" rows {_menu.Scroll + 1}-{Mathf.Min(_menu.Rows.Count, _menu.Scroll + 8)} of {_menu.Rows.Count}" : ""); ((TMP_Text)_footer).text = G('↑', "Up") + G('↓', "/Down") + " rows " + G('←', "Left") + G('→', "/Right") + " tabs Enter run " + G('☆', "+") + " favourite Cheats: " + (Plugin.CheatsEnabled.Value ? "on" : "hidden") + (Plugin.Announce.Value ? ", announced in chat" : "") + text; } private string G(char c, string plain) { if (!((Object)(object)_font != (Object)null) || !_font.HasCharacter(c, true, false)) { return plain; } return c.ToString(); } private int Count() { int num = 0; foreach (Menu.Row row in _menu.Rows) { if (row.Entry != null) { num++; } } return num; } private static bool SafeGet(MenuApi.Entry e) { try { return e.Get(); } catch { return false; } } private void SetFont(TMP_FontAsset f) { _font = f; TextMeshProUGUI[] componentsInChildren = ((Component)this).GetComponentsInChildren<TextMeshProUGUI>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((TMP_Text)componentsInChildren[i]).font = f; } } private static void EnsureEventSystem() { //IL_0013: 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: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)EventSystem.current != (Object)null)) { GameObject val = new GameObject("ModMenu.EventSystem"); Object.DontDestroyOnLoad((Object)val); val.AddComponent<EventSystem>(); val.AddComponent<InputSystemUIInputModule>(); } } private static RectTransform Rect(string name, Transform parent, Vector2 size, Vector2 pos, bool topLeft = false) { //IL_0014: 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) //IL_0024: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(parent, false); if (topLeft) { Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 1f); val.anchorMax = val2; val.anchorMin = val2; val.pivot = new Vector2(0f, 1f); } val.sizeDelta = size; val.anchoredPosition = pos; return val; } private static Image Img(Transform t, Color c) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)t).gameObject.AddComponent<Image>(); ((Graphic)obj).color = c; return obj; } private static void Outline(Transform t, Color c, float w) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Outline obj = ((Component)t).gameObject.AddComponent<Outline>(); ((Shadow)obj).effectColor = c; ((Shadow)obj).effectDistance = new Vector2(w, 0f - w); ((Shadow)obj).useGraphicAlpha = false; } private TextMeshProUGUI Text(Transform parent, string s, float size, Color c, Vector2 pos, Vector2 box, FontStyles style = (FontStyles)0) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = ((Component)Rect("Text", parent, box, pos, topLeft: true)).gameObject.AddComponent<TextMeshProUGUI>(); if ((Object)(object)_font != (Object)null) { ((TMP_Text)val).font = _font; } ((TMP_Text)val).text = s; ((TMP_Text)val).fontSize = size; ((Graphic)val).color = c; ((TMP_Text)val).fontStyle = style; ((TMP_Text)val).enableWordWrapping = false; ((TMP_Text)val).overflowMode = (TextOverflowModes)1; ((Graphic)val).raycastTarget = false; ((TMP_Text)val).richText = true; return val; } private static void Click(Transform t, Action a) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) ((Graphic)(((object)((Component)t).GetComponent<Graphic>()) ?? ((object)Img(t, new Color(0f, 0f, 0f, 0f))))).raycastTarget = true; Button obj = ((Component)t).gameObject.AddComponent<Button>(); ((Selectable)obj).transition = (Transition)0; Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)0; ((Selectable)obj).navigation = navigation; ((UnityEvent)obj.onClick).AddListener((UnityAction)delegate { a(); }); } } public static class PluginInfo { public const string Guid = "daniel.lethalcompany.modmenu"; public const string Name = "ModMenu"; public const string Version = "0.1.0"; } [BepInPlugin("daniel.lethalcompany.modmenu", "ModMenu", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> CheatsEnabled; internal static ConfigEntry<bool> Announce; internal static ConfigEntry<string> OpenKey; internal static ConfigEntry<string> FavouritesCfg; internal static ConfigEntry<string> LastTab; internal static bool InputUtilsLoaded; private readonly Harmony _harmony = new Harmony("daniel.lethalcompany.modmenu"); internal static HashSet<string> Favourites => new HashSet<string>(from s in (FavouritesCfg.Value ?? "").Split(';') where s.Length > 0 select s); private void Awake() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; CheatsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Cheats", "Enabled", true, "Show cheat rows (spawning, Pirate Shop on/off). Cheats only ever run for the host. Off hides them, for a serious run."); Announce = ((BaseUnityPlugin)this).Config.Bind<bool>("Cheats", "Announce", true, "When the host uses a cheat, one grey chat line tells the crew (\"Daniel spawned a safe\")."); OpenKey = ((BaseUnityPlugin)this).Config.Bind<string>("Keys", "Open key", "<Keyboard>/f6", "Opens and closes the menu. Used when LethalCompany InputUtils isn't installed (with it, rebind in Settings > Controls)."); FavouritesCfg = ((BaseUnityPlugin)this).Config.Bind<string>("Saved", "Favourites", "", "Starred rows (tab/label;...). Set from the menu."); LastTab = ((BaseUnityPlugin)this).Config.Bind<string>("Saved", "Last tab", "", "The tab the menu opens on. Set from the menu."); InputUtilsLoaded = Chainloader.PluginInfos.ContainsKey("com.rune580.LethalCompanyInputUtils"); Keys.Init(); GameObject val = new GameObject("ModMenu.Menu"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<Menu>(); _harmony.PatchAll(typeof(Plugin).Assembly); Log.LogInfo((object)("ModMenu 0.1.0 loaded (InputUtils " + (InputUtilsLoaded ? "found" : "not found") + ").")); } internal static void SetFavourite(string key, bool on) { HashSet<string> favourites = Favourites; if (on) { favourites.Add(key); } else { favourites.Remove(key); } FavouritesCfg.Value = string.Join(";", favourites); } } internal static class Keys { private static InputAction _open; internal static string Shown { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) try { return (_open != null && _open.bindings.Count > 0) ? InputActionRebindingExtensions.GetBindingDisplayString(_open, 0, (DisplayStringOptions)0) : "F6"; } catch { return "F6"; } } } internal static void Init() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (Plugin.InputUtilsLoaded) { _open = FromInputUtils(); } if (_open == null) { _open = InputActionSetupExtensions.AddAction(new InputActionMap("ModMenu"), "ModMenu.Open", (InputActionType)1, Plugin.OpenKey.Value, (string)null, (string)null, (string)null, (string)null); _open.Enable(); } _open.performed += delegate { Menu.Instance?.Toggle(); }; } [MethodImpl(MethodImplOptions.NoInlining)] private static InputAction FromInputUtils() { return MenuInputs.Instance.Open; } } internal class MenuInputs : LcInputActions { internal static readonly MenuInputs Instance = new MenuInputs(); [InputAction("<Keyboard>/f6", Name = "Open mod menu")] public InputAction Open { get; set; } } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(HUDManager), "EnableChat_performed")] [HarmonyPrefix] private static bool NoChatWhileOpen() { if (!((Object)(object)Menu.Instance == (Object)null)) { return !Menu.Instance.IsOpen; } return true; } } }