using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FishNet; using Microsoft.CodeAnalysis; using SpongeMods.UILib; using UnityEngine; 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: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("FishNet.Runtime")] [assembly: AssemblyCompany("SpongeMods")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("One in-game menu every Sponge mod puts its settings in.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a149c533da6d929b7267867242f5011f9c2152dc")] [assembly: AssemblyProduct("SpongeMods.ModMenu")] [assembly: AssemblyTitle("SpongeMods.ModMenu")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SpongeMods.ModMenu { internal sealed class Page { private readonly ScrollBox _box; private readonly Column _column; private readonly List _live = new List(); private readonly List _rows = new List(); private readonly List _built = new List(); public RectTransform Rect => _box.Rect; public Page(MenuTab tab, RectTransform parent, Palette theme, bool host) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown _box = new ScrollBox("Page." + tab.Title, parent, theme); _column = new Column(_box.Content); IReadOnlyList rows = tab.Rows; for (int i = 0; i < rows.Count; i++) { MenuRow menuRow = rows[i]; if (!menuRow.HostOnly || host) { RectTransform val = menuRow.Build(_box.Content, theme, _live); _column.Add(val, menuRow.Height); _rows.Add(menuRow); _built.Add(val); } } _box.Measure(_column.Height); } public void Settle() { _column.Rewind(); for (int i = 0; i < _rows.Count; i++) { _column.Add(_built[i], _rows[i].Measured(_built[i])); } _box.Settle(); for (int j = 0; j < _live.Count; j++) { Control obj = _live[j]; Slider val = (Slider)(object)((obj is Slider) ? obj : null); if (val != null) { val.Settle(); } } } public void Step() { _box.Step(); for (int i = 0; i < _live.Count; i++) { _live[i].Step(); _live[i].Animate(); } } public void Stop() { for (int i = 0; i < _live.Count; i++) { _live[i].Cancel(); } } public void Visible(bool visible) { _box.Visible(visible); } } [BepInPlugin("SpongeMods.ModMenu", "Sponge's Mod Menu", "1.0.0")] [BepInDependency("SpongeMods.Core", "1.0.0")] [BepInDependency("SpongeMods.UILib", "1.0.0")] public sealed class ModMenuPlugin : BaseUnityPlugin { public const string Id = "SpongeMods.ModMenu"; public const string Version = "1.0.0"; internal static ConfigEntry OpenKey; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; OpenKey = ((BaseUnityPlugin)this).Config.Bind("Menu", "Open", new KeyboardShortcut((KeyCode)286, Array.Empty()), "Opens and closes the mod menu. It only opens once a world is loaded, and closes on its own if the pause menu or journal opens."); Shell.Current = new Shell(Palette.Default); Log.LogInfo((object)"Mod menu ready."); } private void OnDestroy() { Shell.Current = null; } private void Update() { //IL_0016: 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) Shell current = Shell.Current; if (current == null) { return; } if (!Typing.Active) { KeyboardShortcut value = OpenKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { if (current.Open) { current.Hide(); } else { current.Show(); } } } current.Step(); } } public abstract class MenuRow { public bool HostOnly; public virtual float Height => 30f; internal abstract RectTransform Build(RectTransform parent, Palette theme, List live); internal virtual float Measured(RectTransform built) { return Height; } } internal sealed class HeadingRow : MenuRow { private readonly string _text; public override float Height => 34f; public HeadingRow(string text) { _text = text; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //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) //IL_0023: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Stage.NewRect("Heading", parent); Label val2 = new Label("Text", val, 19f, theme.Accent, true) { Alignment = (TextAnchor)6, Text = _text }; Stage.Spread(val2.Rect, 0f); val2.Rect.offsetMax = new Vector2(0f, -6f); RectTransform rectTransform = ((Graphic)Stage.Fill("Rule", val, Palette.Fade(theme.Rim, 0.45f), 2)).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 0f); rectTransform.pivot = new Vector2(0.5f, 0f); rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; rectTransform.sizeDelta = new Vector2(0f, 2f); return val; } } internal sealed class NoteRow : MenuRow { private readonly string _text; private Label _note; public override float Height => 20f; public NoteRow(string text) { _text = text; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown RectTransform val = Stage.NewRect("Note", parent); _note = new Label("Text", val, 14f, theme.Muted, false) { Alignment = (TextAnchor)0, Wrap = true, Text = _text }; Stage.Spread(_note.Rect, 0f); return val; } internal override float Measured(RectTransform built) { if (_note != null) { return Mathf.Max(Height, _note.MeasureHeight() + 4f); } return Height; } } internal sealed class SwitchRow : MenuRow { private readonly string _text; private readonly Func _get; private readonly Action _set; public SwitchRow(string text, Func get, Action set) { _text = text; _get = get; _set = set; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown Switch val = new Switch(_text, parent, theme, 17f) { On = _get(), Changed = _set }; live.Add((Control)(object)val); return ((Control)val).Rect; } } internal sealed class SliderRow : MenuRow { private readonly string _text; private readonly Func _get; private readonly Action _set; private readonly float _min; private readonly float _max; private readonly bool _whole; public SliderRow(string text, Func get, Action set, float min, float max, bool whole) { _text = text; _get = get; _set = set; _min = min; _max = max; _whole = whole; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //IL_0024: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown Slider val = new Slider(_text, parent, theme, _min, _max, _whole, 0.44f, 17f) { Value = _get(), Changed = _set }; live.Add((Control)(object)val); return ((Control)val).Body; } } internal sealed class ChoiceRow : MenuRow { private readonly string _text; private readonly IReadOnlyList _options; private readonly Func _get; private readonly Action _set; public ChoiceRow(string text, IReadOnlyList options, Func get, Action set) { _text = text; _options = options; _get = get; _set = set; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Chooser val = new Chooser(_text, _options, parent, theme, 0.44f, 16f) { Index = _get(), Changed = _set }; live.Add((Control)(object)val); return ((Control)val).Body; } } internal sealed class TextRow : MenuRow { private const float FieldWidth = 190f; private readonly string _text; private readonly Func _get; private readonly Func _set; private readonly string _hint; public TextRow(string text, Func get, Func set, string hint) { _text = text; _get = get; _set = set; _hint = hint; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //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) //IL_0023: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00f4: 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) RectTransform val = Stage.NewRect("TextRow", parent); Label val2 = new Label("Text", val, 17f, theme.Ink, true) { Alignment = (TextAnchor)3, Text = _text }; Stage.Spread(val2.Rect, 0f); val2.Rect.offsetMax = new Vector2(-202f, 0f); TextBox val3 = new TextBox(val, theme, 16f, (TextAnchor)3) { Value = _get(), Placeholder = _hint, Committed = _set }; ((Control)val3).Rect.anchorMin = new Vector2(1f, 0.5f); ((Control)val3).Rect.anchorMax = new Vector2(1f, 0.5f); ((Control)val3).Rect.pivot = new Vector2(1f, 0.5f); ((Control)val3).Rect.sizeDelta = new Vector2(190f, 28f); ((Control)val3).Rect.anchoredPosition = Vector2.zero; live.Add((Control)(object)val3); return val; } } internal sealed class ActionRow : MenuRow { private const float ButtonWidth = 190f; private readonly string _caption; private readonly string _text; private readonly Action _press; public ActionRow(string caption, string text, Action press) { _caption = caption; _text = text; _press = press; } internal override RectTransform Build(RectTransform parent, Palette theme, List live) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Stage.NewRect("ActionRow", parent); bool num = !string.IsNullOrEmpty(_caption); if (num) { Label val2 = new Label("Text", val, 17f, theme.Ink, true) { Alignment = (TextAnchor)3, Text = _caption }; Stage.Spread(val2.Rect, 0f); val2.Rect.offsetMax = new Vector2(-202f, 0f); } Button val3 = new Button(_text, val, theme, 17f, (TextAnchor)4) { Action = _press }; if (num) { ((Control)val3).Rect.anchorMin = new Vector2(1f, 0.5f); ((Control)val3).Rect.anchorMax = new Vector2(1f, 0.5f); ((Control)val3).Rect.pivot = new Vector2(1f, 0.5f); ((Control)val3).Rect.sizeDelta = new Vector2(190f, 28f); ((Control)val3).Rect.anchoredPosition = Vector2.zero; } else { Stage.Spread(((Control)val3).Rect, 0f); } live.Add((Control)(object)val3); return val; } } internal sealed class Shell { private const float Width = 940f; private const float Height = 640f; private const float Margin = 22f; private const float HeaderHeight = 40f; private const float FooterHeight = 26f; private readonly Palette _theme; private RectTransform _root; private Image _scrim; private Panel _frame; private TabRail _rail; private Label _footer; private readonly List _pages = new List(); private bool _builtForHost; private bool _stale = true; internal static Shell Current { get; set; } public bool Open { get; private set; } private static bool IsHost { get { if ((Object)(object)InstanceFinder.NetworkManager != (Object)null) { return InstanceFinder.IsServerStarted; } return false; } } private Page Active { get { if (_rail == null || _rail.Active < 0 || _rail.Active >= _pages.Count) { return null; } return _pages[_rail.Active]; } } public Shell(Palette theme) { _theme = theme ?? Palette.Default; SpongeMenu.Changed += delegate { _stale = true; }; } public void Show() { if (!Open && Focus.Claim((object)this, (Action)Lost)) { Build(); Open = true; ((Component)_root).gameObject.SetActive(true); for (int i = 0; i < _pages.Count; i++) { _pages[i].Settle(); } TabRail rail = _rail; if (rail != null) { rail.Settle(); } } } public void Hide() { if (Open) { Focus.Release((object)this); Lost(); } } private void Lost() { Open = false; for (int i = 0; i < _pages.Count; i++) { _pages[i].Stop(); } if ((Object)(object)_root != (Object)null) { ((Component)_root).gameObject.SetActive(false); } } public void Step() { if (!Open) { return; } if (_stale || _builtForHost != IsHost) { Rebuild(); return; } _rail.Poll(); Active?.Step(); if (!Typing.Active) { if (Input.GetKeyDown((KeyCode)275)) { _rail.Step(1); } else if (Input.GetKeyDown((KeyCode)276)) { _rail.Step(-1); } } } private void Build() { if (!((Object)(object)_root != (Object)null) || _stale || _builtForHost != IsHost) { Rebuild(); } } private void Rebuild() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Expected O, but got Unknown //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) TabRail rail = _rail; int num = ((rail != null) ? rail.Active : 0); Discard(); _builtForHost = IsHost; _stale = false; _root = Stage.NewRect("SpongeMods.ModMenu", (RectTransform)null); Stage.Spread(_root, 0f); _scrim = Stage.Fill("Scrim", _root, new Color(0f, 0f, 0f, 0.55f), 2); Stage.Spread(((Graphic)_scrim).rectTransform, 0f); _frame = new Panel("Frame", _root, 940f, _theme); _frame.Rect.anchorMin = new Vector2(0.5f, 0.5f); _frame.Rect.anchorMax = new Vector2(0.5f, 0.5f); _frame.Rect.pivot = new Vector2(0.5f, 0.5f); _frame.Rect.sizeDelta = new Vector2(940f, 640f); _frame.Rect.anchoredPosition = Vector2.zero; Top(new Label("Title", _frame.Rect, 26f, _theme.Accent, true) { Alignment = (TextAnchor)3, Text = "Sponge's Mods" }.Rect, 22f, 40f); _footer = new Label("Footer", _frame.Rect, 14f, _theme.Muted, true) { Alignment = (TextAnchor)3 }; _footer.Rect.anchorMin = new Vector2(0f, 0f); _footer.Rect.anchorMax = new Vector2(1f, 0f); _footer.Rect.pivot = new Vector2(0.5f, 0f); _footer.Rect.offsetMin = new Vector2(22f, 8f); _footer.Rect.offsetMax = new Vector2(-22f, 34f); _rail = new TabRail(_frame.Rect, _theme); Top(_rail.Rect, 22f, TabRail.Height); _rail.Rect.anchoredPosition = new Vector2(0f, -62f); _rail.Changed = ShowPage; float num2 = 62f + TabRail.Height + 8f; float num3 = 42f; IReadOnlyList tabs = SpongeMenu.Tabs; for (int i = 0; i < tabs.Count; i++) { Page page = new Page(tabs[i], _frame.Rect, _theme, _builtForHost); page.Rect.anchorMin = new Vector2(0f, 0f); page.Rect.anchorMax = new Vector2(1f, 1f); page.Rect.offsetMin = new Vector2(22f, num3); page.Rect.offsetMax = new Vector2(-22f, 0f - num2); _pages.Add(page); _rail.Add(tabs[i].Title); } if (_pages.Count == 0) { Empty(num2, num3); } _rail.Settle(); _rail.Active = Mathf.Clamp(num, 0, Mathf.Max(0, _pages.Count - 1)); ShowPage(_rail.Active); _footer.Text = (_builtForHost ? "You are the host — settings marked for the host apply to everyone." : "The host owns the world's settings; yours apply to you alone."); ((Component)_root).gameObject.SetActive(Open); if (Open) { for (int j = 0; j < _pages.Count; j++) { _pages[j].Settle(); } } } private void Empty(float top, float bottom) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) Label val = new Label("Empty", _frame.Rect, 17f, _theme.Muted, true) { Alignment = (TextAnchor)0, Wrap = true, Text = "No mod has added anything here yet. Sponge mods put their settings in this menu, so this fills up as you install them." }; val.Rect.anchorMin = new Vector2(0f, 0f); val.Rect.anchorMax = new Vector2(1f, 1f); val.Rect.offsetMin = new Vector2(22f, bottom); val.Rect.offsetMax = new Vector2(-22f, 0f - top); } private void ShowPage(int index) { for (int i = 0; i < _pages.Count; i++) { _pages[i].Visible(i == index); } } private static void Top(RectTransform rect, float margin, float height) { //IL_000b: 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) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = new Vector2(0f, 1f); rect.anchorMax = new Vector2(1f, 1f); rect.pivot = new Vector2(0.5f, 1f); rect.offsetMin = new Vector2(margin, 0f); rect.offsetMax = new Vector2(0f - margin, 0f); rect.sizeDelta = new Vector2(rect.sizeDelta.x, height); rect.anchoredPosition = new Vector2(0f, 0f - margin); } private void Discard() { _pages.Clear(); _rail = null; _frame = null; _footer = null; _scrim = null; if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)((Component)_root).gameObject); } _root = null; } } public static class SpongeMenu { private static readonly List _tabs = new List(); internal static IReadOnlyList Tabs => _tabs; public static bool IsOpen => Shell.Current?.Open ?? false; internal static event Action Changed; public static MenuTab Tab(string owner, string title, int order = 100) { if (string.IsNullOrEmpty(owner)) { throw new ArgumentException("A tab must name the plugin that owns it.", "owner"); } for (int i = 0; i < _tabs.Count; i++) { if (_tabs[i].Owner == owner && _tabs[i].Title == title) { return _tabs[i]; } } MenuTab menuTab = new MenuTab(owner, title, order); _tabs.Add(menuTab); _tabs.Sort(delegate(MenuTab left, MenuTab right) { int num = left.Order.CompareTo(right.Order); return (num == 0) ? string.Compare(left.Title, right.Title, StringComparison.Ordinal) : num; }); Touch(); return menuTab; } internal static void Touch() { SpongeMenu.Changed?.Invoke(); } public static void Open() { Shell.Current?.Show(); } public static void Close() { Shell.Current?.Hide(); } } public sealed class MenuTab { private readonly List _rows = new List(); public string Owner { get; } public string Title { get; } public int Order { get; } internal IReadOnlyList Rows => _rows; internal MenuTab(string owner, string title, int order) { Owner = owner; Title = title; Order = order; } private MenuTab Add(MenuRow row) { _rows.Add(row); SpongeMenu.Touch(); return this; } public MenuTab Heading(string text) { return Add(new HeadingRow(text)); } public MenuTab Note(string text) { return Add(new NoteRow(text)); } public MenuTab Toggle(ConfigEntry setting) { return Toggle((setting != null) ? ((ConfigEntryBase)setting).Definition.Key : null, setting); } public MenuTab Toggle(string text, ConfigEntry setting) { if (setting == null) { return this; } return Toggle(text, () => setting.Value, delegate(bool value) { setting.Value = value; }); } public MenuTab Toggle(string text, Func get, Action set) { return Add(new SwitchRow(text, get, set)); } public MenuTab Number(ConfigEntry setting) { return Number((setting != null) ? ((ConfigEntryBase)setting).Definition.Key : null, setting); } public MenuTab Number(string text, ConfigEntry setting) { if (setting == null) { return this; } ConfigDescription description = ((ConfigEntryBase)setting).Description; if (((description != null) ? description.AcceptableValues : null) is AcceptableValueRange val) { return Number(text, setting, val.MinValue, val.MaxValue); } int result; return Field(text, () => setting.Value.ToString(), (string typed) => (!int.TryParse(typed, out result)) ? setting.Value.ToString() : (setting.Value = result).ToString()); } public MenuTab Number(string text, ConfigEntry setting, int low, int high) { if (setting == null) { return this; } return Add(new SliderRow(text, () => setting.Value, delegate(float value) { setting.Value = Mathf.RoundToInt(value); }, low, high, whole: true)); } public MenuTab Number(ConfigEntry setting) { return Number((setting != null) ? ((ConfigEntryBase)setting).Definition.Key : null, setting); } public MenuTab Number(string text, ConfigEntry setting) { if (setting == null) { return this; } ConfigDescription description = ((ConfigEntryBase)setting).Description; if (((description != null) ? description.AcceptableValues : null) is AcceptableValueRange val) { return Number(text, setting, val.MinValue, val.MaxValue); } float result; return Field(text, () => setting.Value.ToString(CultureInfo.InvariantCulture), (string typed) => (!float.TryParse(typed, NumberStyles.Float, CultureInfo.InvariantCulture, out result)) ? setting.Value.ToString(CultureInfo.InvariantCulture) : (setting.Value = result).ToString(CultureInfo.InvariantCulture)); } public MenuTab Number(string text, ConfigEntry setting, float low, float high) { if (setting == null) { return this; } return Add(new SliderRow(text, () => setting.Value, delegate(float value) { setting.Value = value; }, low, high, whole: false)); } public MenuTab Number(string text, Func get, Action set, float low, float high, bool whole = false) { return Add(new SliderRow(text, get, set, low, high, whole)); } public MenuTab Choice(string text, IReadOnlyList options, Func get, Action set) { return Add(new ChoiceRow(text, options, get, set)); } public MenuTab Choice(string text, ConfigEntry setting) where TEnum : struct, Enum { if (setting == null) { return this; } string[] names = Enum.GetNames(typeof(TEnum)); TEnum[] values = (TEnum[])Enum.GetValues(typeof(TEnum)); return Choice(text, names, () => Array.IndexOf(values, setting.Value), delegate(int index) { if (index >= 0 && index < values.Length) { setting.Value = values[index]; } }); } public MenuTab Field(string text, ConfigEntry setting, string hint = "") { if (setting == null) { return this; } return Field(text, () => setting.Value, (string typed) => setting.Value = typed, hint); } public MenuTab Field(string text, Func get, Func set, string hint = "") { return Add(new TextRow(text, get, set, hint)); } public MenuTab Press(string label, Action press) { return Add(new ActionRow(null, label, press)); } public MenuTab Press(string caption, string label, Action press) { return Add(new ActionRow(caption, label, press)); } public MenuTab OnlyHost() { if (_rows.Count > 0) { _rows[_rows.Count - 1].HostOnly = true; } return this; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }