using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DistanceModConfigurationManager.DistanceGUI.Controls; using DistanceModConfigurationManager.DistanceGUI.Data; using DistanceModConfigurationManager.DistanceGUI.Events; using DistanceModConfigurationManager.DistanceGUI.Menu; using DistanceModConfigurationManager.Game; using DistanceModConfigurationManager.Internal; using Events; using Events.Menu; using HarmonyLib; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("DistanceModConfigurationManager")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DistanceModConfigurationManager")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9bc754f3-4bbe-4c84-b06a-79311691dd74")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] public static class System__EnumExtensions { public static bool HasFlag(this T value, T flag) where T : struct { ulong num = Convert.ToUInt64(value); ulong num2 = Convert.ToUInt64(flag); return (num & num2) != 0; } } namespace DistanceModConfigurationManager { internal sealed class ConfigSettingEntry : SettingEntryBase { public ConfigEntryBase Entry { get; } public override Type SettingType => Entry.SettingType; public ConfigSettingEntry(ConfigEntryBase entry, BaseUnityPlugin owner) { Entry = entry; DispName = entry.Definition.Key; base.Category = entry.Definition.Section; ConfigDescription description = entry.Description; base.Description = ((description != null) ? description.Description : null); TypeConverter converter = TomlTypeConverter.GetConverter(entry.SettingType); if (converter != null) { base.ObjToStr = (object o) => converter.ConvertToString(o, entry.SettingType); base.StrToObj = (string s) => converter.ConvertToObject(s, entry.SettingType); } ConfigDescription description2 = entry.Description; AcceptableValueBase val = ((description2 != null) ? description2.AcceptableValues : null); if (val != null) { GetAcceptableValues(val); } base.DefaultValue = entry.DefaultValue; ConfigDescription description3 = entry.Description; SetFromAttributes((description3 != null) ? description3.Tags : null, owner); } private void GetAcceptableValues(AcceptableValueBase values) { Type type = ((object)values).GetType(); PropertyInfo property = type.GetProperty("AcceptableValues", BindingFlags.Instance | BindingFlags.Public); if ((object)property != null) { base.AcceptableValues = ((IEnumerable)property.GetValue(values, null)).Cast().ToArray(); return; } PropertyInfo property2 = type.GetProperty("MinValue", BindingFlags.Instance | BindingFlags.Public); PropertyInfo property3 = type.GetProperty("MaxValue", BindingFlags.Instance | BindingFlags.Public); if ((object)property2 != null && (object)property3 != null) { base.AcceptableValueRange = new KeyValuePair(property2.GetValue(values, null), property3.GetValue(values, null)); base.ShowRangeAsPercent = ((base.AcceptableValueRange.Key.Equals(0) || base.AcceptableValueRange.Key.Equals(1)) && base.AcceptableValueRange.Value.Equals(100)) || (base.AcceptableValueRange.Key.Equals(0f) && base.AcceptableValueRange.Value.Equals(1f)); } } public override object Get() { return Entry.BoxedValue; } protected override void SetValue(object newVal) { Entry.BoxedValue = newVal; } } [BepInPlugin("Distance.DistanceModConfigurationManager", "Distance Mod Configuration Manager", "1.2.1")] public sealed class Mod : BaseUnityPlugin { private const string modGUID = "Distance.DistanceModConfigurationManager"; private const string modName = "Distance Mod Configuration Manager"; public const string modVersion = "1.2.1"; public static string ShowVersionKey = "Show Version Info"; private List _modsWithoutSettings; private List _allSettings; private List _filteredSettings = new List(); private static readonly Harmony harmony = new Harmony("Distance.DistanceModConfigurationManager"); public static ManualLogSource Log = new ManualLogSource("Distance Mod Configuration Manager"); public static Mod Instance; public static ConfigEntry ShowVersionInfo { get; set; } public int modsLoaded { get; set; } private void Awake() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null) { Instance = this; } Log = Logger.CreateLogSource("Distance.DistanceModConfigurationManager"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Thanks for using the Distance Mod Configuration Manager!"); ShowVersionInfo = ((BaseUnityPlugin)this).Config.Bind("General", ShowVersionKey, true, new ConfigDescription("Display the Config Manager Version in the main menu", (AcceptableValueBase)null, new object[0])); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading..."); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded!"); } private void OnConfigChanged(object sender, EventArgs e) { SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null); if (e2 != null) { } } private static bool IsKeyboardShortcut(SettingEntryBase x) { return (object)x.SettingType == typeof(KeyboardShortcut) || (object)x.SettingType == typeof(KeyCode); } public void BuildSettingList() { SettingSearcher.CollectSettings(out var results, out var modsWithoutSettings); _modsWithoutSettings = modsWithoutSettings; _allSettings = results.ToList(); Log.LogInfo((object)("Settings found: " + results.Count())); foreach (SettingEntryBase item in results) { Log.LogInfo((object)item.PluginInfo.Name); } BuildFilteredSettingList(); } private void BuildFilteredSettingList() { IEnumerable allSettings = _allSettings; allSettings = allSettings.Where((SettingEntryBase x) => x.IsAdvanced != true); foreach (SettingEntryBase item in allSettings) { Log.LogInfo((object)("Filtered List: " + item.DispName)); } List list = new List(); string text = string.Empty; foreach (SettingEntryBase setting in allSettings) { if (text != setting.PluginInfo.Name) { text = setting.PluginInfo.Name; list.Add(new PluginSettingsData { Info = setting.PluginInfo, Settings = new List { setting } }); } else { PluginSettingsData pluginSettingsData = list.Find((PluginSettingsData plugin) => plugin.Info == setting.PluginInfo); pluginSettingsData.Settings.Add(setting); } } _filteredSettings = list; modsLoaded = list.Count + _modsWithoutSettings.Count - 1; AddFilteredSettingsToMenu(); } private void AddFilteredSettingsToMenu() { foreach (PluginSettingsData filteredSetting in _filteredSettings) { MenuTree menuTree = new MenuTree("menu.distance.mod." + Regex.Replace(filteredSetting.Info.Name, "\\s+", "").ToLower(), filteredSetting.Info.Name.ToUpper() + " SETTINGS"); List list = new List(); foreach (SettingEntryBase setting in filteredSetting.Settings) { if (list.Any()) { if (ListEx.Last(list) != setting.Category) { list.Add(setting.Category); } } else { list.Add(setting.Category); } } if (list.Count >= 900) { foreach (string item in list) { MenuTree menuTree2 = new MenuTree("submenu.distance.mod." + Regex.Replace(filteredSetting.Info.Name, "\\s+", "").ToLower(), item.ToUpper()); foreach (SettingEntryBase setting2 in filteredSetting.Settings) { if (menuTree2.Title == setting2.Category.ToUpper()) { menuTree2.Add(CreateUIForSetting(setting2)); } } menuTree.Add(new SubMenu(MenuDisplayMode.Both, "submenu:" + item.ToLower(), item.ToUpper()).NavigatesTo(menuTree2).WithDescription(Regex.Replace(filteredSetting.Info.Name, "\\s+", "") + " settings related to " + item)); } } else { foreach (SettingEntryBase setting3 in filteredSetting.Settings) { menuTree.Add(CreateUIForSetting(setting3)); } } Menus.AddNew(MenuDisplayMode.Both, menuTree, filteredSetting.Info.Name.ToUpper(), "Settings for the " + filteredSetting.Info.Name + " mod"); } } private MenuItemBase CreateUIForSetting(SettingEntryBase setting) { if ((object)typeof(bool) == setting.SettingType) { return new CheckBox(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).WithGetter(() => (bool)setting.Get()).WithSetter(delegate(bool x) { setting.Set(x); }).WithDescription(setting.Description ?? ""); } if ((object)typeof(float) == setting.SettingType) { if (setting.AcceptableValueRange.Key == null) { return new FloatSlider(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).LimitedByRange((float)setting.DefaultValue - 180f, (float)setting.DefaultValue + 180f).WithDefaultValue((float)setting.DefaultValue).WithGetter(() => (float)setting.Get()) .WithSetter(delegate(float x) { setting.Set(x); }) .WithDescription(setting.Description ?? ""); } return new FloatSlider(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).LimitedByRange((float)setting.AcceptableValueRange.Key, (float)setting.AcceptableValueRange.Value).WithDefaultValue((float)setting.DefaultValue).WithGetter(() => (float)setting.Get()) .WithSetter(delegate(float x) { setting.Set(x); }) .WithDescription(setting.Description ?? ""); } if ((object)typeof(int) == setting.SettingType) { if (setting.AcceptableValueRange.Key == null) { return new IntegerSlider(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).LimitedByRange((int)setting.DefaultValue, (int)setting.DefaultValue + 60).WithDefaultValue((int)setting.DefaultValue).WithGetter(() => (int)setting.Get()) .WithSetter(delegate(int x) { setting.Set(x); }) .WithDescription(setting.Description ?? ""); } return new IntegerSlider(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).LimitedByRange((int)setting.AcceptableValueRange.Key, (int)setting.AcceptableValueRange.Value).WithDefaultValue((int)setting.DefaultValue).WithGetter(() => (int)setting.Get()) .WithSetter(delegate(int x) { setting.Set(x); }) .WithDescription(setting.Description ?? ""); } if ((object)typeof(string) == setting.SettingType) { return new InputPrompt(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).WithDefaultValue((string)setting.DefaultValue).WithTitle(setting.DispName).WithSubmitAction(delegate(string x) { setting.Set(x); }) .WithDescription(setting.Description ?? ""); } if (setting.SettingType.IsEnum) { Dictionary entries = Enum.GetNames(setting.SettingType).ToDictionary((string name) => name, (string name) => (int)Enum.Parse(setting.SettingType, name)); return new ListBox(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).WithEntries(entries).WithGetter(() => (int)setting.Get()).WithSetter(delegate(int x) { setting.Set(x); }) .WithDescription(setting.Description ?? ""); } if ((object)typeof(KeyboardShortcut) == setting.SettingType) { return new InputPrompt(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).WithDefaultValue(setting.DefaultValue.ToString()).WithCurrentValue(setting.Get().ToString()).WithTitle(setting.DispName) .WithSubmitAction(delegate(string x) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) setting.Set(KeyboardShortcut.Deserialize(x)); }) .WithDescription(setting.Description ?? ""); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Could not properly display " + setting.DispName + " in the menu")); return new EmptyElement(MenuDisplayMode.Both, "settings:" + Regex.Replace(setting.DispName, "\\s+", "_").ToLower(), setting.DispName.ToUpper()).WithDescription("This setting is not properly displayed! Report this problem to the #modding channel on the Distance discord!"); } } public sealed class PluginSettingsData { public BepInPlugin Info; public List Settings; } internal class PropertySettingEntry : SettingEntryBase { private Type _settingType; public object Instance { get; internal set; } public PropertyInfo Property { get; internal set; } public override string DispName { get { return string.IsNullOrEmpty(base.DispName) ? Property.Name : base.DispName; } protected internal set { base.DispName = value; } } public override Type SettingType => _settingType ?? (_settingType = Property.PropertyType); public PropertySettingEntry(object instance, PropertyInfo settingProp, BaseUnityPlugin pluginInstance) { SetFromAttributes(settingProp.GetCustomAttributes(inherit: false), pluginInstance); if (!base.Browsable.HasValue) { base.Browsable = settingProp.CanRead && settingProp.CanWrite; } base.ReadOnly = settingProp.CanWrite; Property = settingProp; Instance = instance; } public override object Get() { return Property.GetValue(Instance, null); } protected override void SetValue(object newVal) { Property.SetValue(Instance, newVal, null); } } public abstract class SettingEntryBase { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); private static readonly PropertyInfo[] _myProperties = typeof(SettingEntryBase).GetProperties(BindingFlags.Instance | BindingFlags.Public); public object[] AcceptableValues { get; protected set; } public KeyValuePair AcceptableValueRange { get; protected set; } public bool? ShowRangeAsPercent { get; protected set; } public Action CustomDrawer { get; private set; } public CustomHotkeyDrawerFunc CustomHotkeyDrawer { get; private set; } public bool? Browsable { get; protected set; } public string Category { get; protected set; } public object DefaultValue { get; protected set; } public bool HideDefaultButton { get; protected set; } public bool HideSettingName { get; protected set; } public string Description { get; protected internal set; } public virtual string DispName { get; protected internal set; } public BepInPlugin PluginInfo { get; protected internal set; } public bool? ReadOnly { get; protected set; } public abstract Type SettingType { get; } public BaseUnityPlugin PluginInstance { get; private set; } public bool? IsAdvanced { get; internal set; } public int Order { get; protected set; } public Func ObjToStr { get; internal set; } public Func StrToObj { get; internal set; } public abstract object Get(); public void Set(object newVal) { if (ReadOnly != true) { SetValue(newVal); } } protected abstract void SetValue(object newVal); internal void SetFromAttributes(object[] attribs, BaseUnityPlugin pluginInstance) { PluginInstance = pluginInstance; PluginInfo = ((pluginInstance != null) ? pluginInstance.Info.Metadata : null); if (attribs == null || attribs.Length == 0) { return; } foreach (object obj in attribs) { object obj2 = obj; object obj3 = obj2; if (obj3 == null) { continue; } if (!(obj3 is DisplayNameAttribute displayNameAttribute)) { if (!(obj3 is CategoryAttribute categoryAttribute)) { if (!(obj3 is DescriptionAttribute descriptionAttribute)) { if (!(obj3 is DefaultValueAttribute defaultValueAttribute)) { if (!(obj3 is ReadOnlyAttribute readOnlyAttribute)) { if (!(obj3 is BrowsableAttribute browsableAttribute)) { Action action = obj3 as Action; if (action == null) { if (obj3 is string text) { switch (text) { case "ReadOnly": ReadOnly = true; break; case "Browsable": Browsable = true; break; case "Unbrowsable": case "Hidden": Browsable = false; break; case "Advanced": IsAdvanced = true; break; } continue; } Type type = obj.GetType(); if (!(type.Name == "ConfigurationManagerAttributes")) { break; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (var item in from my in _myProperties join other in fields on my.Name equals other.Name select new { my, other }) { try { object obj4 = item.other.GetValue(obj); if (obj4 != null) { if ((object)item.my.PropertyType != item.other.FieldType && typeof(Delegate).IsAssignableFrom(item.my.PropertyType)) { obj4 = Delegate.CreateDelegate(item.my.PropertyType, ((Delegate)obj4).Target, ((Delegate)obj4).Method); } item.my.SetValue(this, obj4, null); } } catch (Exception ex) { Mod.Log.LogWarning((object)("Failed to copy value " + item.my.Name + " from provided tag object " + type.FullName + " - " + ex.Message)); } } } else { CustomDrawer = delegate { action(this); }; } } else { Browsable = browsableAttribute.Browsable; } } else { ReadOnly = readOnlyAttribute.IsReadOnly; } } else { DefaultValue = defaultValueAttribute.Value; } } else { Description = descriptionAttribute.Description; } } else { Category = categoryAttribute.Category; } } else { DispName = displayNameAttribute.DisplayName; } } } } internal static class SettingSearcher { private static readonly ICollection _updateMethodNames = new string[4] { "Update", "FixedUpdate", "LateUpdate", "OnGUI" }; public static BaseUnityPlugin[] FindPlugins() { return (from x in Chainloader.PluginInfos.Values select x.Instance into plugin where (Object)(object)plugin != (Object)null select plugin).Union(Object.FindObjectsOfType(typeof(BaseUnityPlugin)).Cast()).ToArray(); } public static void CollectSettings(out IEnumerable results, out List modsWithoutSettings) { modsWithoutSettings = new List(); try { results = GetBepInExCoreConfig(); } catch (Exception ex) { results = Enumerable.Empty(); Mod.Log.LogError((object)ex); } BaseUnityPlugin[] array = FindPlugins(); foreach (BaseUnityPlugin val in array) { Type type = ((object)val).GetType(); BepInPlugin metadata = val.Info.Metadata; string text = ((metadata != null) ? metadata.Name : null) ?? ((object)val).GetType().FullName; Mod.Log.LogInfo((object)("The name of plugin found: " + text)); if (type.GetCustomAttributes(typeof(BrowsableAttribute), inherit: false).Cast().Any((BrowsableAttribute x) => !x.Browsable)) { modsWithoutSettings.Add(text); continue; } List list = new List(); list.AddRange(GetPluginConfig(val).Cast()); list.RemoveAll((SettingEntryBase x) => x.Browsable == false); if (list.Count == 0) { modsWithoutSettings.Add(text); } if (list.Count <= 0) { continue; } results = results.Concat(list); foreach (SettingEntryBase item in list) { Mod.Log.LogInfo((object)item.DispName); } } } private static IEnumerable GetBepInExCoreConfig() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown PropertyInfo property = typeof(ConfigFile).GetProperty("CoreConfig", BindingFlags.Static | BindingFlags.NonPublic); if ((object)property == null) { throw new ArgumentNullException("coreConfigProp"); } ConfigFile source = (ConfigFile)property.GetValue(null, null); BepInPlugin bepinMeta = new BepInPlugin("BepInEx", "BepInEx", typeof(Chainloader).Assembly.GetName().Version.ToString()); return ((IEnumerable>)source).Select((Func, SettingEntryBase>)((KeyValuePair kvp) => new ConfigSettingEntry(kvp.Value, null) { IsAdvanced = true, PluginInfo = bepinMeta })); } private static IEnumerable GetPluginConfig(BaseUnityPlugin plugin) { return ((IEnumerable>)plugin.Config).Select((KeyValuePair kvp) => new ConfigSettingEntry(kvp.Value, plugin)); } } internal static class Utils { public static string ToProperClass(this string str) { if (string.IsNullOrEmpty(str)) { return string.Empty; } if (str.Length < 2) { return str; } string text = str.Substring(0, 1).ToUpper(); for (int i = 1; i < str.Length; i++) { if (char.IsUpper(str[i])) { text += " "; } text += str[i]; } return text; } public static string AppendZero(this string s) { return (!s.Contains(".")) ? (s + ".0") : s; } public static string AppendZeroIfFloat(this string s, Type type) { return ((object)type == typeof(float) || (object)type == typeof(double) || (object)type == typeof(decimal)) ? s.AppendZero() : s; } } } namespace DistanceModConfigurationManager.Internal { internal class VersionNumber : MonoBehaviour { private static class MathUtil { public static float Map(float s, float a1, float a2, float b1, float b2) { return b1 + (s - a1) * (b2 - b1) / (a2 - a1); } } internal const float MaximumOpacity = 0.7f; internal static bool creatingInstance; internal UILabel label; internal UIWidget widget; internal UIPanel panel; private bool _visible = true; private Coroutine _transitionCoroutine = null; internal static VersionNumber Instance { get; set; } internal bool Visible { get { return Visible; } set { if (value != _visible) { if (_transitionCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_transitionCoroutine); } _transitionCoroutine = ((MonoBehaviour)this).StartCoroutine(Transition(value)); } _visible = value; } } internal bool CanDisplay { get { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_006d: Invalid comparison between Unknown and I4 bool flag = true; bool num = flag; Scene activeScene = SceneManager.GetActiveScene(); flag = num & string.Equals(((Scene)(ref activeScene)).name, "mainmenu", StringComparison.InvariantCultureIgnoreCase); flag &= G.Sys.MenuPanelManager_.panelStack_.Count == 2; flag &= Mod.ShowVersionInfo.Value; flag &= G.Sys.GameManager_.IsLevelLoaded_; return flag & ((int)G.Sys.GameManager_.BlackFade_.currentState_ == 0); } } internal static void Create(GameObject speedrunTimerLogic = null) { if (Object.op_Implicit((Object)(object)Instance) || creatingInstance) { return; } creatingInstance = true; GameObject val = null; val = ((!Object.op_Implicit((Object)(object)speedrunTimerLogic)) ? GameObject.Find("Anchor : Speedrun Timer") : GameObjectEx.Parent(speedrunTimerLogic)); if (Object.op_Implicit((Object)(object)val)) { GameObject val2 = Object.Instantiate(val, val.transform.parent); val2.SetActive(true); ((Object)val2).name = "Anchor : Mod Manager Info"; GameObjectEx.ForEachChildObjectDepthFirstRecursive(val2, (Action)delegate(GameObject obj) { obj.SetActive(true); GameObjectEx.RemoveComponent(obj); }); UILabel componentInChildren = val2.GetComponentInChildren(); Instance = ((Component)componentInChildren).gameObject.AddComponent(); } creatingInstance = false; } internal void Start() { GameObject val = GameObjectEx.Parent(((Component)this).gameObject); GameObject val2 = GameObjectEx.Parent(val); label = ((Component)this).GetComponent(); widget = val.GetComponent(); panel = val2.GetComponent(); ((UIRect)widget).alpha = 0f; AdjustPosition(); } internal void Update() { label.text = string.Format("DISTANCE MOD CONFIGURATION {0} - {1} MOD(S) LOADED", "1.2.1", Mod.Instance.modsLoaded); Visible = CanDisplay; } internal void AdjustPosition() { ((UIRect)label).SetAnchor(((Component)panel).gameObject, 21, 19, -19, -17); ((UIWidget)label).pivot = (Pivot)0; } internal IEnumerator Transition(bool visible, float duration = 0.2f) { float target = (visible ? 0.7f : 0f); float current = ((UIRect)widget).alpha; for (float time = 0f; time < duration; time += Timex.deltaTime_) { if (!G.Sys.OptionsManager_.General_.menuAnimations_) { break; } float value = MathUtil.Map(time, 0f, duration, current, target); ((UIRect)widget).alpha = value; yield return null; } ((UIRect)widget).alpha = target; } } } namespace DistanceModConfigurationManager.Patches { [HarmonyPatch(typeof(OptionsMenuLogic), "DisplaySubmenu")] internal static class OptionsMenuLogic__DisplaySubmenu { [HarmonyPrefix] internal static bool Prefix(OptionsMenuLogic __instance, string submenuName) { List list = __instance.subMenus_.ToList(); OptionsSubmenu val = list.Find((OptionsSubmenu x) => x.Name_ == submenuName); if (Object.op_Implicit((Object)(object)val) && val is ModdingMenu) { ModdingMenu moddingMenu = val as ModdingMenu; if (!moddingMenu.MenuTree.Any()) { MenuSystem.ShowUnavailableMessage(); return false; } } return true; } } [HarmonyPatch(typeof(OptionsMenuLogic), "GetSubmenus")] internal static class OptionsMenuLogic__GetSubmenus { [HarmonyPrefix] internal static void Prefix(OptionsMenuLogic __instance) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) OptionsSubmenu[] subMenus_ = __instance.subMenus_; foreach (OptionsSubmenu val in subMenus_) { if (((object)val).GetType().IsSubclassOf(typeof(SuperMenu))) { MenuSystem.MenuBlueprint = ((SuperMenu)val).menuBlueprint_; } } ModdingMenu moddingMenu = ((Component)__instance).gameObject.AddComponent(); moddingMenu.MenuTree = MenuSystem.MenuTree; List list = new List(__instance.subMenus_); OptionsSubmenu[] subMenus_2 = __instance.subMenus_; foreach (OptionsSubmenu val2 in subMenus_2) { if (val2.Name_ == ((OptionsSubmenu)moddingMenu).Name_) { list.Remove(val2); } } list.Add((OptionsSubmenu)(object)moddingMenu); __instance.subMenus_ = list.ToArray(); } } [HarmonyPatch(typeof(SpeedrunTimerLogic), "OnEnable")] internal static class SpeedrunTimerLogic__OnEnable { [HarmonyPostfix] internal static void Postfix(SpeedrunTimerLogic __instance) { try { VersionNumber.Create(((Component)__instance).gameObject); } catch (Exception ex) { Mod.Log.LogError((object)ex); } } } [HarmonyPatch(typeof(SplashScreenLogic), "Start")] internal static class SplashScreenLogic__Start { [HarmonyPostfix] internal static void CreateSettingList() { Mod.Instance.BuildSettingList(); } } } namespace DistanceModConfigurationManager.Game { public static class Menus { public static void AddNew(MenuDisplayMode displayMode, MenuTree menuTree, string description = null) { AddNew(displayMode, menuTree, menuTree.Title, description); } public static void AddNew(MenuDisplayMode displayMode, MenuTree menuTree, string title, string description = null) { try { MenuSystem.MenuTree.Add(new SubMenu(displayMode, menuTree.Id, title).NavigatesTo(menuTree).WithDescription(description)); Mod.Log.LogInfo((object)("Added new menu tree: '" + menuTree.Id + "', '" + menuTree.Title + "'...")); } catch (Exception ex) { Mod.Log.LogError((object)("Failed to add the menu tree: '" + menuTree.Id + "', '" + menuTree.Title + "'.")); Mod.Log.LogError((object)ex); } } } public sealed class MessageBox { private readonly string Message = ""; private readonly string Title = ""; private float Time = 0f; private ButtonType Buttons = (ButtonType)0; private Action Confirm; private Action Cancel; private MessageBox(string message, string title) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) Message = message; Title = title; Confirm = EmptyAction; Cancel = EmptyAction; } public static MessageBox Create(string content, string title = "") { return new MessageBox(content, title); } public MessageBox SetButtons(ButtonType buttons) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) Buttons = buttons; return this; } public MessageBox SetTimeout(float delay) { Time = delay; return this; } public MessageBox OnConfirm(Action action) { Confirm = action; return this; } public MessageBox OnCancel(Action action) { Cancel = action; return this; } public void Show() { //IL_001e: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0042: Expected O, but got Unknown G.Sys.MenuPanelManager_.ShowMessage(Message, Title, (OnButtonClicked)delegate { Confirm(); }, (OnButtonClicked)delegate { Cancel(); }, Buttons, false, (Pivot)4, Time); } private void EmptyAction() { } } } namespace DistanceModConfigurationManager.DistanceGUI.Menu { public static class MenuSystem { internal static GameObject MenuBlueprint { get; set; } internal static MenuTree MenuTree { get; set; } static MenuSystem() { MenuTree = new MenuTree("menu.distancemodding.main", "Configure Distance Mods"); } internal static void ShowMenu(MenuTree menuTree, ModdingMenu parentMenu, int pageIndex) { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown if (menuTree.GetItems().Count == 0) { ShowUnavailableMessage(); return; } ModdingMenu[] components = ((OptionsSubmenu)parentMenu).PanelObject_.GetComponents(); foreach (ModdingMenu moddingMenu in components) { GameObjectEx.Destroy((Object)(object)moddingMenu); } ModdingMenu menu = ComponentEx.GetOrAddComponent((Component)(object)Mod.Instance); menu.MenuTree = menuTree; menu.CurrentPageIndex = pageIndex; menu.MenuPanel = MenuPanel.Create(((OptionsSubmenu)menu).PanelObject_, true, true, false, true, true, true); menu.MenuPanel.backgroundOpacity_ = 0.75f; MenuPanel menuPanel = menu.MenuPanel; menuPanel.onIsTopChanged_ = (OnIsTopChanged)Delegate.Combine((Delegate?)(object)menuPanel.onIsTopChanged_, (Delegate?)(OnIsTopChanged)delegate(bool isTop) { if (isTop) { menu.ResetAnimations(); } else if (G.Sys.MenuPanelManager_.panelStack_.Contains(menu.MenuPanel)) { menu.SwitchPage(menu.CurrentPageIndex, relative: false); } else { menu.SwitchPage(0, relative: false); } }); MenuPanel menuPanel2 = menu.MenuPanel; menuPanel2.onPanelPop_ = (OnPanelPop)Delegate.Combine((Delegate?)(object)menuPanel2.onPanelPop_, (Delegate?)(OnPanelPop)delegate { if (!G.Sys.MenuPanelManager_.panelStack_.Contains(menu.MenuPanel)) { menu.SwitchPage(0, relative: false); ((OptionsSubmenu)parentMenu).PanelObject_.SetActive(true); if (menu.MenuTree != MenuTree) { GameObjectEx.Destroy((Object)(object)((OptionsSubmenu)menu).PanelObject_); } GameObjectEx.Destroy((Object)(object)menu); } }); ((OptionsSubmenu)parentMenu).PanelObject_.SetActive(false); menu.MenuPanel.Push(); } public static void ShowUnavailableMessage() { MessageBox.Create("This menu is currently unavailable.\nNo menu entries found.", "MOD SETTINGS MANAGER").SetButtons((ButtonType)0).Show(); } public static MenuDisplayMode GetCurrentDisplayMode() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); if (string.Equals(((Scene)(ref activeScene)).name, "mainmenu", StringComparison.OrdinalIgnoreCase)) { return MenuDisplayMode.MainMenu; } return MenuDisplayMode.PauseMenu; } } public class ModdingMenu : ModdingMenuAbstract { private const int MaxEntriesPerPage = 9; private InputManager InputManager { get; set; } private SuperDuperMenu MenuController { get { GameObject panelObject_ = ((OptionsSubmenu)this).PanelObject_; return (panelObject_ != null) ? panelObject_.GetComponent() : null; } } private GameObject[] Blueprints => (GameObject[])(object)new GameObject[4] { MenuController.actionBlueprint_, MenuController.sliderBlueprint_, MenuController.popupBlueprint_, MenuController.toggleBlueprint_ }; private int PageCount => (int)Math.Max(Math.Ceiling((float)MenuTree.Count / 9f), 1.0); private UIExFancyFadeInMenu MenuFade { get { GameObject panelObject_ = ((OptionsSubmenu)this).PanelObject_; return (panelObject_ != null) ? panelObject_.GetComponent() : null; } } public override string Title => MenuTree.Title; public GameObject TitleLabel => ((Component)((OptionsSubmenu)this).PanelObject_.transform.Find("MenuTitleTemplate/UILabel - Title")).gameObject; public GameObject DescriptionLabel => ((Component)((OptionsSubmenu)this).PanelObject_.transform.Find("MenuTitleTemplate/UILabel - Description")).gameObject; public GameObject OptionsTable => ((Component)((OptionsSubmenu)this).PanelObject_.transform.Find("Options/OptionsTable")).gameObject; public MenuPanel MenuPanel { get; internal set; } public MenuTree MenuTree { get; internal set; } = new MenuTree("menu.modding.error", "[FF0000]Error[-]"); public string Description { get; set; } public int CurrentPageIndex { get; internal set; } = 0; public string Id => MenuTree.Id; public override void InitializeVirtual() { InputManager = G.Sys.InputManager_; DisplayMenu(); StaticEvent.Broadcast(new MenuOpened.Data(this)); } private void DisplayMenu() { MenuTree items = MenuTree.GetItems(MenuSystem.GetCurrentDisplayMode()); if (items.Any()) { for (int i = CurrentPageIndex * 9; i < CurrentPageIndex * 9 + 9 && i < items.Count; i++) { items[i]?.Tweak(this); } return; } MessageBox.Create("This menu is currently unavailable.\nNo menu entries found.", "MOD SETTINGS MANAGER").SetButtons((ButtonType)0).OnConfirm(delegate { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown MenuPanel topPanel_ = base.PanelManager.TopPanel_; topPanel_.onPanelPop_ = (OnPanelPop)Delegate.Combine((Delegate?)(object)topPanel_.onPanelPop_, (Delegate?)(OnPanelPop)delegate { MenuPanel.Pop(); }); }) .Show(); } public void OnEnable() { ResetAnimations(); } public void HideElements() { GameObject[] children = GameObjectEx.GetChildren(OptionsTable); foreach (GameObject val in children) { if (!Blueprints.Contains(val)) { UIWidget orAddComponent = GameObjectEx.GetOrAddComponent(val); ((UIRect)orAddComponent).alpha = 0f; } } } public void ResetAnimations() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) List list = new List(); GameObject[] children = GameObjectEx.GetChildren(OptionsTable); foreach (GameObject val in children) { if (!Blueprints.Contains(val)) { UIExFancyFadeIn orAddComponent = GameObjectEx.GetOrAddComponent(val); list.Add(orAddComponent); } } Vector2 val2 = PrimitiveEx.ToVector2(float.MinValue); Vector2 val3 = PrimitiveEx.ToVector2(float.MaxValue); foreach (UIExFancyFadeIn item in list) { UIWidget component = ((Component)item).GetComponent(); Vector2 val4 = Vector2.op_Implicit(component.worldCenter); float num = 1f - Mathf.InverseLerp(val3.y, val2.y, val4.y); item.offset_ = new Vector3(MenuFade.offset_, 0f); item.duration_ = MenuFade.duration_; item.delay_ = num * MenuFade.delay_; item.offset_.x *= -1f; item.initialAlpha_ = 1f; ((UIRect)component).alpha = 1f; item.Init(); } } public void SwitchPage(int value = 0, bool relative = true, bool resetObjects = true) { //IL_02bf: Unknown result type (might be due to invalid IL or missing references) if (relative) { CurrentPageIndex += value; } else { CurrentPageIndex = value; } CurrentPageIndex = ((CurrentPageIndex < 0) ? (PageCount - 1) : ((CurrentPageIndex <= PageCount - 1) ? CurrentPageIndex : 0)); if (!resetObjects) { return; } foreach (GameObject item in MenuController.items_) { if (SuperDuperMenu.defaultFloatValues_.ContainsKey(((Object)item).name)) { SuperDuperMenu.defaultFloatValues_.Remove(((Object)item).name); } UIWidget component = item.GetComponent(); if (Object.op_Implicit((Object)(object)component) && MenuFade.widgets_.Contains(component)) { MenuFade.widgets_.Remove(component); } GameObjectEx.DeactivateAndDestroy(item.gameObject); } MenuController.items_.Clear(); foreach (UIButton value2 in MenuController.actions_.Values) { destroyObject(((Component)value2).gameObject); } foreach (UIToggle value3 in MenuController.toggles_.Values) { destroyObject(((Component)value3).gameObject); } foreach (SliderHelper value4 in MenuController.sliders_.Values) { destroyObject(((Component)value4).gameObject); } foreach (PopupHelper value5 in MenuController.popups_.Values) { destroyObject(((Component)value5).gameObject); } MenuController.actions_.Clear(); MenuController.toggles_.Clear(); MenuController.sliders_.Clear(); MenuController.popups_.Clear(); MenuController.buttonsTable_.Reposition(); MenuController.SetDescription((GameObject)null, ""); StaticEvent.Broadcast(new Data(string.Empty, true, string.Empty)); MenuController.Init((SuperMenu)(object)this); MenuController.Initialize(); static void destroyObject(GameObject obj) { obj.transform.parent = null; GameObjectEx.DeactivateAndDestroy(obj); Object.DestroyImmediate((Object)(object)obj); } } public override void Update() { if (!((Object)(object)((OptionsSubmenu)this).PanelObject_ == (Object)null)) { GameObject panelObject_ = ((OptionsSubmenu)this).PanelObject_; if (((panelObject_ != null) ? new bool?(panelObject_.activeInHierarchy) : ((bool?)null)) ?? true) { UpdateVirtual(); } } } public override void UpdateVirtual() { bool flag = MenuTree.Count > 9; G.Sys.MenuPanelManager_.SetBottomLeftActionButtonEnabled((InputAction)41, flag); G.Sys.MenuPanelManager_.SetBottomLeftActionButtonEnabled((InputAction)40, flag); G.Sys.MenuPanelManager_.SetBottomLeftActionButton((InputAction)41, "PREVIOUS"); G.Sys.MenuPanelManager_.SetBottomLeftActionButton((InputAction)40, "NEXT"); if (flag) { if (InputManager.GetKeyUp((InputAction)41, -2)) { SwitchPage(-1); } if (InputManager.GetKeyUp((InputAction)40, -2)) { SwitchPage(1); } } Description = $"Page {CurrentPageIndex + 1} of {PageCount}"; GameObject titleLabel = TitleLabel; if (titleLabel != null) { titleLabel.SetActive(true); } UILabel component = TitleLabel.GetComponent(); (((SuperMenu)this).menu_.menuTitleLabel_ ?? component).text = Title; GameObject descriptionLabel = DescriptionLabel; if (descriptionLabel != null) { descriptionLabel.SetActive(true); } UILabel component2 = DescriptionLabel.GetComponent(); MenuDescriptionLabel menuDescriptionLabel_ = ((SuperMenu)this).menu_.menuDescriptionLabel_; string text_ = (component2.text = Description); menuDescriptionLabel_.text_ = text_; } } public abstract class ModdingMenuAbstract : SuperMenu { public MenuPanelManager PanelManager => G.Sys.MenuPanelManager_; public abstract string Title { get; } public override string MenuTitleName_ => Title; public override string Name_ => "Mod Settings"; public override bool DisplayInMenu(bool isPauseMenu) { return true; } protected ModdingMenuAbstract() { base.menuBlueprint_ = MenuSystem.MenuBlueprint; } public override void InitializeVirtual() { } public virtual void UpdateVirtual() { } public virtual void Update() { } public override void OnPanelPop() { } } } namespace DistanceModConfigurationManager.DistanceGUI.Events { public class MenuClosed : StaticEvent { public struct Data { public ModdingMenu menu; public Data(ModdingMenu m) { menu = m; } } } public class MenuOpened : StaticEvent { public struct Data { public ModdingMenu menu; public Data(ModdingMenu m) { menu = m; } } } } namespace DistanceModConfigurationManager.DistanceGUI.Data { [Flags] public enum MenuDisplayMode { None = 0, MainMenu = 1, PauseMenu = 2, Both = 3 } public class MenuItemInfo : MonoBehaviour { public string Id => Item?.Id; public MenuItemBase Item { get; set; } } public class MenuTree : List { public string Title { get; set; } public string Id { get; set; } public MenuTree(string id, string title) { Id = id; Title = title; } public ActionButton ActionButton(MenuDisplayMode displayMode, string id, string name, Action action, string description = null) { MenuItemBase menuItemBase = new ActionButton(displayMode, id, name).WhenClicked(action).WithDescription(description); Add(menuItemBase); return menuItemBase as ActionButton; } public CheckBox CheckBox(MenuDisplayMode displayMode, string id, string name, Func getter, Action setter, string description = null) { MenuItemBase menuItemBase = new CheckBox(displayMode, id, name).WithGetter(getter).WithSetter(setter).WithDescription(description); Add(menuItemBase); return menuItemBase as CheckBox; } public FloatSlider FloatSlider(MenuDisplayMode displayMode, string id, string name, Func getter, Action setter, float minimum = 0f, float maximum = 1f, float defaultValue = 0f, string description = null) { MenuItemBase menuItemBase = new FloatSlider(displayMode, id, name).WithGetter(getter).WithSetter(setter).LimitedByRange(minimum, maximum) .WithDefaultValue(defaultValue) .WithDescription(description); Add(menuItemBase); return menuItemBase as FloatSlider; } public IntegerSlider IntegerSlider(MenuDisplayMode displayMode, string id, string name, Func getter, Action setter, int minimum = 0, int maximum = 10, int defaultValue = 0, string description = null) { MenuItemBase menuItemBase = new IntegerSlider(displayMode, id, name).WithGetter(getter).WithSetter(setter).LimitedByRange(minimum, maximum) .WithDefaultValue(defaultValue) .WithDescription(description); Add(menuItemBase); return menuItemBase as IntegerSlider; } public InputPrompt InputPrompt(MenuDisplayMode displayMode, string id, string name, Action submitAction, Action closeAction = null, Func validator = null, string title = null, string defaultValue = null, string description = null) { MenuItemBase menuItemBase = new InputPrompt(displayMode, id, name).WithSubmitAction(submitAction).WithCloseAction(closeAction).ValidatedBy(validator) .WithTitle(title) .WithDefaultValue(defaultValue) .WithDescription(description); Add(menuItemBase); return menuItemBase as InputPrompt; } public PasswordPrompt PasswordPrompt(MenuDisplayMode displayMode, string id, string name, Action submitAction, Action closeAction, Func validator, string title = null, string defaultValue = null, string description = null) { MenuItemBase menuItemBase = new PasswordPrompt(displayMode, id, name).WithSubmitAction(submitAction).WithCloseAction(closeAction).ValidatedBy(validator) .WithTitle(title) .WithDefaultValue(defaultValue) .WithDescription(description); Add(menuItemBase); return menuItemBase as PasswordPrompt; } public ListBox ListBox(MenuDisplayMode displayMode, string id, string name, Func getter, Action setter, Dictionary entries, string description = null) { MenuItemBase menuItemBase = new ListBox(displayMode, id, name).WithGetter(getter).WithSetter(setter).WithEntries(entries) .WithDescription(description); Add(menuItemBase); return menuItemBase as ListBox; } public SubMenu SubmenuButton(MenuDisplayMode displayMode, string id, string name, MenuTree menuTree, string description = null) { MenuItemBase menuItemBase = new SubMenu(displayMode, id, name).NavigatesTo(menuTree).WithDescription(description); Add(menuItemBase); return menuItemBase as SubMenu; } public MenuTree GetItems(MenuDisplayMode mode) { MenuTree menuTree = new MenuTree(Id, Title); ICollectionEx.AddRange((ICollection)menuTree, this.Where((MenuItemBase item) => System__EnumExtensions.HasFlag(item.Mode, mode))); return menuTree; } public MenuTree GetItems() { return GetItems(MenuSystem.GetCurrentDisplayMode()); } public static implicit operator SubMenu(MenuTree menu) { return new SubMenu(MenuDisplayMode.Both, menu.Id, menu.Title); } } } namespace DistanceModConfigurationManager.DistanceGUI.Controls { public class ActionButton : MenuItemBase { public Action OnClick { get; set; } public ActionButton(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { } public ActionButton WhenClicked(Action onClick) { OnClick = onClick; return this; } public override void Tweak(ModdingMenu menu) { if (OnClick == null) { throw new InvalidOperationException("OnClick action not initialized. Use WhenClicked() to configure the action."); } ((SuperMenu)menu).TweakAction(base.Name, OnClick, base.Description); base.Tweak(menu); } } public class CheckBox : MenuItemBase { public Func Get { get; set; } public Action Set { get; set; } public bool DefaultValue { get; private set; } public CheckBox(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { Get = () => DefaultValue; Set = delegate { }; } public CheckBox WithDefaultValue(bool defaultValue) { DefaultValue = defaultValue; return this; } public CheckBox WithGetter(Func getter) { Get = getter ?? throw new ArgumentNullException("Getter cannot be null"); return this; } public CheckBox WithSetter(Action setter) { Set = setter ?? throw new ArgumentNullException("Setter cannot be null."); return this; } public override void Tweak(ModdingMenu menu) { if (Get == null || Set == null) { throw new InvalidOperationException("Cannot call Tweak with Get or Set being null."); } ((SuperMenu)menu).TweakBool(base.Name, Get(), Set, base.Description); base.Tweak(menu); } } internal class EmptyElement : MenuItemBase { public EmptyElement() : base(MenuDisplayMode.Both, "empty", string.Empty) { } public EmptyElement(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { } } public class FloatSlider : MenuItemBase { public float Minimum { get; private set; } = 0f; public float Maximum { get; private set; } = 1f; public Func Get { get; set; } public Action Set { get; set; } public float DefaultValue { get; set; } public FloatSlider(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { Get = () => DefaultValue; Set = delegate { }; } public FloatSlider WithDefaultValue(float defaultValue) { if (defaultValue > Maximum || defaultValue < Minimum) { throw new ArgumentOutOfRangeException($"Default value ({defaultValue}) must be between minimum ({Minimum}) and maximum ({Maximum}) values."); } DefaultValue = defaultValue; return this; } public FloatSlider LimitedByRange(float minimum, float maximum) { if (Minimum > Maximum) { throw new ArgumentException("Minimum must be lower than maximum."); } Minimum = minimum; Maximum = maximum; return this; } public FloatSlider WithGetter(Func getter) { Get = getter ?? throw new ArgumentNullException("Getter cannot be null."); return this; } public FloatSlider WithSetter(Action setter) { Set = setter ?? throw new ArgumentNullException("Setter cannot be null."); return this; } public override void Tweak(ModdingMenu menu) { if (Get == null || Set == null) { throw new InvalidOperationException("Cannot call Tweak with Get or Set method being null."); } ((SuperMenu)menu).TweakFloat(base.Name, Get(), Minimum, Maximum, DefaultValue, Set, base.Description); base.Tweak(menu); } } public class InputPrompt : MenuItemBase { public string Title { get; set; } public string CurrentValue { get; set; } public Func DefaultValue { get; set; } public Func Validator { get; set; } public Action SubmitAction { get; set; } public Action CloseAction { get; set; } public InputPrompt(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { } public InputPrompt WithTitle(string title) { Title = title ?? string.Empty; return this; } public InputPrompt WithCurrentValue(string currentValue) { CurrentValue = currentValue ?? string.Empty; return this; } public InputPrompt WithDefaultValue(string defaultValue) { DefaultValue = () => defaultValue; return this; } public InputPrompt WithDefaultValue(Func defaultValue) { DefaultValue = defaultValue ?? ((Func)(() => string.Empty)); return this; } public InputPrompt WithSubmitAction(Action submitAction) { SubmitAction = submitAction ?? throw new ArgumentNullException("Submit action cannot be null."); return this; } public InputPrompt WithCloseAction(Action closeAction) { CloseAction = closeAction; return this; } public InputPrompt ValidatedBy(Func validator) { Validator = validator; return this; } protected virtual bool OnSubmit(out string error, string input) { error = Validator?.Invoke(input); if (error == null) { SubmitAction?.Invoke(input); CurrentValue = input; return true; } return false; } protected virtual void OnCancel() { CloseAction?.Invoke(this); } protected virtual void OnTweak() { //IL_0009: 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) //IL_004b: Expected O, but got Unknown //IL_004b: Expected O, but got Unknown InputPromptPanel.Create(new OnSubmit(OnSubmit), new OnPop(OnCancel), Title, (CurrentValue == string.Empty) ? DefaultValue() : CurrentValue); } public override void Tweak(ModdingMenu menu) { ((SuperMenu)menu).TweakAction(base.Name, (Action)delegate { OnTweak(); base.Tweak(menu); }, base.Description); } } public class IntegerSlider : MenuItemBase { public int Minimum { get; set; } public int Maximum { get; set; } public Func Get { get; set; } public Action Set { get; set; } public int DefaultValue { get; set; } public IntegerSlider(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { Get = () => DefaultValue; Set = delegate { }; } public IntegerSlider WithGetter(Func getter) { Get = getter ?? throw new ArgumentNullException("Getter cannot be null."); return this; } public IntegerSlider WithSetter(Action setter) { Set = setter ?? throw new ArgumentNullException("Setter cannot be null."); return this; } public IntegerSlider WithDefaultValue(int defaultValue) { if (defaultValue > Maximum || defaultValue < Minimum) { throw new ArgumentOutOfRangeException($"Default value ({defaultValue}) must be between minimum ({Minimum}) and maximum ({Maximum}) values."); } DefaultValue = defaultValue; return this; } public IntegerSlider LimitedByRange(int minimum, int maximum) { if (Minimum > Maximum) { throw new ArgumentOutOfRangeException("Minimum must be lower than maximum."); } Minimum = minimum; Maximum = maximum; return this; } public override void Tweak(ModdingMenu menu) { if (Get == null || Set == null) { throw new InvalidOperationException("Cannot invoke tweak with Get or Set being null."); } ((SuperMenu)menu).TweakInt(base.Name, Get(), Minimum, Maximum, DefaultValue, Set, base.Description); base.Tweak(menu); } } public class ListBox : MenuItemBase { public Func Get { get; set; } public Action Set { get; set; } public Dictionary Entries { get; set; } public ListBox(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { } public ListBox WithGetter(Func getter) { Get = getter ?? throw new ArgumentNullException("Getter cannot be null."); return this; } public ListBox WithSetter(Action setter) { Set = setter ?? throw new ArgumentNullException("Setter cannot be null."); return this; } public ListBox WithEntries(Dictionary entries) { if (entries == null) { entries = new Dictionary(); } Entries = entries; return this; } public override void Tweak(ModdingMenu menu) { if (Get == null || Set == null) { throw new InvalidOperationException("Cannot call TweakEnum with Get or Set being null."); } ((SuperMenu)menu).TweakEnum(base.Name, Get, Set, base.Description, ICollectionEx.ToArray>((ICollection>)Entries)); base.Tweak(menu); } } public abstract class MenuItemBase { public MenuDisplayMode Mode { get; } public string Id { get; } public string Name { get; set; } public string Description { get; set; } protected MenuItemBase(MenuDisplayMode mode, string id, string name) { Mode = mode; Id = id; Name = name; } public MenuItemBase WithDescription(string description) { Description = description; return this; } public virtual void Tweak(ModdingMenu menu) { GameObject[] array = (from x in GameObjectEx.GetChildren(menu.OptionsTable) where string.Equals(((Object)x).name, Name) select x).ToArray(); GameObject val = null; if (array.Length != 0) { val = array[0]; } if ((Object)(object)val != (Object)null) { MenuItemInfo menuItemInfo = val.AddComponent(); menuItemInfo.Item = this; } } } public class PasswordPrompt : InputPrompt { public PasswordPrompt(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { } protected override void OnTweak() { //IL_0009: 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) //IL_0031: Expected O, but got Unknown //IL_0031: Expected O, but got Unknown InputPromptPanel.CreatePassword(new OnSubmit(OnSubmit), new OnPop(OnCancel), base.Title, base.DefaultValue()); } } public class SubMenu : MenuItemBase { public MenuTree MenuTree { get; private set; } public SubMenu(MenuDisplayMode mode, string id, string name) : base(mode, id, name) { } public SubMenu NavigatesTo(MenuTree menuTree) { MenuTree = menuTree; return this; } public override void Tweak(ModdingMenu menu) { ((SuperMenu)menu).TweakAction(base.Name, (Action)delegate { MenuSystem.ShowMenu(MenuTree, menu, 0); base.Tweak(menu); }, base.Description); } } }