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 ModConfigs v1.1.1
ModConfigs.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GUIFramework; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using Valheim.SettingsGui; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("ModConfigs")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("ModConfigs")] [assembly: AssemblyTitle("ModConfigs")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.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 ModdedWolfsConfigs { public static class ModdedWolfsConfigsAPI { public static void OpenConfigPanel() { ConfigPanelOpener.Open(); } } public sealed class ConfigurationManagerAttributes { public bool? Browsable; public bool? IsAdminOnly; public bool? IsAdvanced; public int? Order; public string DispName; public string Description; public string Category; public bool? ReadOnly; public bool? HideDefaultButton; public object DefaultValue; public bool? ShowRangeAsPercent; public bool? HideSettingName; } internal static class ClientLocalBindings { internal static bool IsBinding(ConfigEntryBase entry) { if (entry == null) { return false; } Type settingType = entry.SettingType; if (settingType == null) { return false; } if (settingType == typeof(KeyCode) || settingType == typeof(KeyboardShortcut)) { return true; } return (settingType.FullName ?? string.Empty).IndexOf("KeyboardShortcut", StringComparison.OrdinalIgnoreCase) >= 0; } } internal static class ConfigApply { internal static event Action<ConfigEntryBase> LocalChanged; internal static void PersistAfterLocalChange(ConfigEntryBase entry) { if (entry == null) { return; } try { ConfigFile configFile = entry.ConfigFile; if (configFile != null) { configFile.Save(); } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to save config: " + ex.Message)); } ConfigDiscovery.RefreshRuntimeValues(entry.ConfigFile); try { ConfigApply.LocalChanged?.Invoke(entry); } catch (Exception ex2) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Config change listener failed: " + ex2.Message)); } } } internal sealed class DiscoveredPlugin { public string Guid; public string Name; public string Version; public BaseUnityPlugin Plugin; public List<DiscoveredSection> Sections = new List<DiscoveredSection>(); } internal sealed class DiscoveredSection { public string Name; public List<ConfigEntryBase> Entries = new List<ConfigEntryBase>(); } internal static class ConfigDiscovery { private sealed class ReferenceComparer<T> : IEqualityComparer<T> where T : class { internal static readonly ReferenceComparer<T> Instance = new ReferenceComparer<T>(); public bool Equals(T x, T y) { return x == y; } public int GetHashCode(T obj) { return RuntimeHelpers.GetHashCode(obj); } } private static readonly HashSet<string> HiddenConfigKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "LastSelectedModGuid", "ShowMenuButton" }; private static readonly Dictionary<ConfigFile, MethodInfo> RuntimeRefreshers = new Dictionary<ConfigFile, MethodInfo>(ReferenceComparer<ConfigFile>.Instance); private static bool _loggedHiddenKeyFilter; private static List<DiscoveredPlugin> _cache; private static bool _cacheValid; private static bool _cachedHideSelf; private static bool _cachedShowAdvanced; internal static void InvalidateCache() { _cacheValid = false; _cache = null; } internal static bool IsHiddenConfigKey(string key) { if (!string.IsNullOrEmpty(key)) { return HiddenConfigKeys.Contains(key); } return false; } internal static bool ShouldRenderEntry(ConfigEntryBase entry) { if (((entry != null) ? entry.Definition : null) == (ConfigDefinition)null) { return false; } return !IsHiddenConfigKey(entry.Definition.Key); } internal static List<DiscoveredPlugin> Discover() { bool flag = ModdedWolfsConfigsPlugin.HideSelfFromList != null && ModdedWolfsConfigsPlugin.HideSelfFromList.Value; bool flag2 = ModdedWolfsConfigsPlugin.ShowAdvancedSettings != null && ModdedWolfsConfigsPlugin.ShowAdvancedSettings.Value; if (_cacheValid && _cache != null && _cachedHideSelf == flag && _cachedShowAdvanced == flag2) { return _cache; } List<DiscoveredPlugin> result = (_cache = DiscoverUncached()); _cacheValid = true; _cachedHideSelf = flag; _cachedShowAdvanced = flag2; return result; } private static List<DiscoveredPlugin> DiscoverUncached() { List<DiscoveredPlugin> list = new List<DiscoveredPlugin>(); IEnumerable<KeyValuePair<string, PluginInfo>> enumerable; try { enumerable = Chainloader.PluginInfos.Where(delegate(KeyValuePair<string, PluginInfo> p) { PluginInfo value5 = p.Value; return ((value5 != null) ? value5.Metadata : null) != null; }).OrderBy<KeyValuePair<string, PluginInfo>, string>((KeyValuePair<string, PluginInfo> p) => p.Value.Metadata.Name ?? p.Value.Metadata.GUID ?? p.Key ?? string.Empty, StringComparer.OrdinalIgnoreCase).ToList(); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("ConfigDiscovery: failed to enumerate plugins: " + ex.Message)); return list; } HashSet<ConfigFile> hashSet = new HashSet<ConfigFile>(ReferenceComparer<ConfigFile>.Instance); foreach (KeyValuePair<string, PluginInfo> item in enumerable) { try { PluginInfo value = item.Value; object obj; if (value == null) { obj = null; } else { BaseUnityPlugin instance = value.Instance; obj = ((instance != null) ? instance.Config : null); } ConfigFile val = (ConfigFile)obj; if (val != null) { hashSet.Add(val); } } catch { } } Dictionary<BaseUnityPlugin, List<ConfigFile>> dictionary = MapAssemblyConfigFiles(enumerable, hashSet); foreach (KeyValuePair<string, PluginInfo> item2 in enumerable) { PluginInfo value2 = item2.Value; string text = item2.Key ?? "(unknown)"; try { if (((value2 != null) ? value2.Metadata : null) == null) { continue; } text = ((!string.IsNullOrEmpty(value2.Metadata.Name)) ? (value2.Metadata.Name + " (" + value2.Metadata.GUID + ")") : (value2.Metadata.GUID ?? item2.Key ?? "(unknown)")); BaseUnityPlugin instance2 = value2.Instance; if ((Object)(object)instance2 == (Object)null || (ModdedWolfsConfigsPlugin.HideSelfFromList.Value && value2.Metadata.GUID == "ModdedWolf.ModConfigs")) { continue; } List<ConfigFile> list2 = CollectConfigFiles(instance2, hashSet); if (dictionary.TryGetValue(instance2, out var value3)) { foreach (ConfigFile item3 in value3) { if (!list2.Contains(item3)) { list2.Add(item3); } } } if (list2.Count == 0) { continue; } Dictionary<string, DiscoveredSection> dictionary2 = new Dictionary<string, DiscoveredSection>(StringComparer.OrdinalIgnoreCase); HashSet<ConfigEntryBase> hashSet2 = new HashSet<ConfigEntryBase>(ReferenceComparer<ConfigEntryBase>.Instance); foreach (ConfigFile item4 in list2) { foreach (ConfigDefinition key in item4.Keys) { if (key == (ConfigDefinition)null) { continue; } if (IsHiddenConfigKey(key.Key)) { if (!_loggedHiddenKeyFilter && value2.Metadata.GUID == "ModdedWolf.ModConfigs") { _loggedHiddenKeyFilter = true; ModdedWolfsConfigsPlugin.Log.LogInfo((object)("ConfigDiscovery: hiding internal key '" + key.Key + "' from UI (still stored in cfg).")); } continue; } ConfigEntryBase val2 = item4[key]; if (!(((val2 != null) ? val2.Definition : null) == (ConfigDefinition)null) && hashSet2.Add(val2) && IsBrowsable(val2)) { string text2 = key.Section ?? string.Empty; if (!dictionary2.TryGetValue(text2, out var value4)) { value4 = (dictionary2[text2] = new DiscoveredSection { Name = text2 }); } value4.Entries.Add(val2); } } } if (dictionary2.Count == 0) { continue; } DiscoveredPlugin discoveredPlugin = new DiscoveredPlugin { Guid = (value2.Metadata.GUID ?? item2.Key ?? string.Empty), Name = (value2.Metadata.Name ?? value2.Metadata.GUID ?? item2.Key ?? "Unknown"), Version = (value2.Metadata.Version?.ToString() ?? ""), Plugin = instance2 }; foreach (DiscoveredSection item5 in dictionary2.Values.OrderByDescending(SectionHasBinding).ThenByDescending((DiscoveredSection s) => string.Equals(s.Name, "General", StringComparison.OrdinalIgnoreCase)).ThenBy<DiscoveredSection, string>((DiscoveredSection s) => s.Name ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { item5.Entries = item5.Entries.OrderByDescending(ClientLocalBindings.IsBinding).ThenByDescending(GetOrder).ThenBy<ConfigEntryBase, string>(delegate(ConfigEntryBase e) { ConfigDefinition definition = e.Definition; return ((definition != null) ? definition.Key : null) ?? string.Empty; }, StringComparer.OrdinalIgnoreCase) .ToList(); discoveredPlugin.Sections.Add(item5); } list.Add(discoveredPlugin); } catch (Exception ex2) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("ConfigDiscovery: skipped plugin '" + text + "': " + ex2.Message)); } } return list; } private static List<ConfigFile> CollectConfigFiles(BaseUnityPlugin plugin, HashSet<ConfigFile> builtInConfigs) { List<ConfigFile> list = new List<ConfigFile>(); HashSet<ConfigFile> hashSet = new HashSet<ConfigFile>(ReferenceComparer<ConfigFile>.Instance); ConfigFile config = plugin.Config; if (config != null && hashSet.Add(config)) { list.Add(config); } for (Type type = ((object)plugin).GetType(); type != null && type != typeof(BaseUnityPlugin); type = type.BaseType) { FieldInfo[] fields; try { fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { continue; } FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { ConfigFile val = null; try { object obj2 = (fieldInfo.IsStatic ? null : plugin); if (typeof(ConfigFile).IsAssignableFrom(fieldInfo.FieldType)) { object? value = fieldInfo.GetValue(obj2); val = (ConfigFile)((value is ConfigFile) ? value : null); } else if (typeof(ConfigEntryBase).IsAssignableFrom(fieldInfo.FieldType)) { object? value2 = fieldInfo.GetValue(obj2); object? obj3 = ((value2 is ConfigEntryBase) ? value2 : null); val = ((obj3 != null) ? ((ConfigEntryBase)obj3).ConfigFile : null); } } catch { continue; } if (val != null && !builtInConfigs.Contains(val) && hashSet.Add(val)) { list.Add(val); } } } return list; } private static Dictionary<BaseUnityPlugin, List<ConfigFile>> MapAssemblyConfigFiles(IEnumerable<KeyValuePair<string, PluginInfo>> plugins, HashSet<ConfigFile> builtInConfigs) { Dictionary<BaseUnityPlugin, List<ConfigFile>> dictionary = new Dictionary<BaseUnityPlugin, List<ConfigFile>>(ReferenceComparer<BaseUnityPlugin>.Instance); Dictionary<Assembly, List<BaseUnityPlugin>> dictionary2 = new Dictionary<Assembly, List<BaseUnityPlugin>>(); foreach (KeyValuePair<string, PluginInfo> plugin in plugins) { BaseUnityPlugin val; try { PluginInfo value = plugin.Value; val = ((value != null) ? value.Instance : null); } catch { continue; } if (!((Object)(object)val == (Object)null)) { Assembly assembly = ((object)val).GetType().Assembly; if (!dictionary2.TryGetValue(assembly, out var value2)) { value2 = (dictionary2[assembly] = new List<BaseUnityPlugin>()); } value2.Add(val); } } foreach (KeyValuePair<Assembly, List<BaseUnityPlugin>> item in dictionary2) { List<ConfigFile> list2; try { list2 = ScanAssemblyStaticConfigFiles(item.Key); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("ConfigDiscovery: failed to scan " + item.Key.GetName().Name + ": " + ex.Message)); continue; } if (list2.Count == 0) { continue; } MethodInfo methodInfo = null; bool flag = false; foreach (ConfigFile item2 in list2) { if (builtInConfigs.Contains(item2)) { continue; } BaseUnityPlugin val2 = ((item.Value.Count == 1) ? item.Value[0] : MatchOwnerByFileName(item.Value, item2)); if ((Object)(object)val2 == (Object)null) { continue; } if (!dictionary.TryGetValue(val2, out var value3)) { value3 = (dictionary[val2] = new List<ConfigFile>()); } if (!value3.Contains(item2)) { value3.Add(item2); } if (!flag) { methodInfo = FindRuntimeRefresher(item.Key); flag = true; } if (methodInfo != null) { lock (RuntimeRefreshers) { RuntimeRefreshers[item2] = methodInfo; } } } } return dictionary; } private static List<ConfigFile> ScanAssemblyStaticConfigFiles(Assembly assembly) { List<ConfigFile> list = new List<ConfigFile>(); HashSet<ConfigFile> hashSet = new HashSet<ConfigFile>(ReferenceComparer<ConfigFile>.Instance); foreach (Type loadableType in GetLoadableTypes(assembly)) { FieldInfo[] fields; try { if (loadableType == null || loadableType.ContainsGenericParameters || typeof(BaseUnityPlugin).IsAssignableFrom(loadableType) || loadableType.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false)) { continue; } fields = loadableType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); goto IL_0076; } catch { } continue; IL_0076: FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { ConfigFile val = null; try { if (typeof(ConfigFile).IsAssignableFrom(fieldInfo.FieldType)) { object? value = fieldInfo.GetValue(null); val = (ConfigFile)((value is ConfigFile) ? value : null); } else if (typeof(ConfigEntryBase).IsAssignableFrom(fieldInfo.FieldType)) { object? value2 = fieldInfo.GetValue(null); object? obj2 = ((value2 is ConfigEntryBase) ? value2 : null); val = ((obj2 != null) ? ((ConfigEntryBase)obj2).ConfigFile : null); } } catch { continue; } if (val != null && hashSet.Add(val)) { list.Add(val); } } } return list; } private static IEnumerable<Type> GetLoadableTypes(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type t) => t != null); } catch { return Array.Empty<Type>(); } } private static BaseUnityPlugin MatchOwnerByFileName(List<BaseUnityPlugin> owners, ConfigFile file) { string text; try { text = Path.GetFileNameWithoutExtension(file.ConfigFilePath) ?? string.Empty; } catch { return null; } BaseUnityPlugin val = null; foreach (BaseUnityPlugin owner in owners) { PluginInfo info = owner.Info; BepInPlugin val2 = ((info != null) ? info.Metadata : null); if (val2 != null) { if (string.Equals(text, val2.Name, StringComparison.OrdinalIgnoreCase) || string.Equals(text, val2.GUID, StringComparison.OrdinalIgnoreCase)) { return owner; } if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(val2.Name) && text.IndexOf(val2.Name, StringComparison.OrdinalIgnoreCase) >= 0) { val = owner; } } } return val; } private static MethodInfo FindRuntimeRefresher(Assembly assembly) { MethodInfo methodInfo = null; foreach (Type loadableType in GetLoadableTypes(assembly)) { MethodInfo method; try { if (loadableType == null || loadableType.ContainsGenericParameters) { continue; } method = loadableType.GetMethod("getValues", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); goto IL_0044; } catch { } continue; IL_0044: if (!(method == null)) { if (methodInfo != null) { return null; } methodInfo = method; } } return methodInfo; } internal static void RefreshRuntimeValues(ConfigFile file) { if (file == null) { return; } MethodInfo value; lock (RuntimeRefreshers) { if (!RuntimeRefreshers.TryGetValue(file, out value)) { return; } } try { value.Invoke(null, null); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("ConfigDiscovery: " + value.DeclaringType?.FullName + "." + value.Name + " failed: " + (ex.InnerException?.Message ?? ex.Message))); } } private static bool IsBrowsable(ConfigEntryBase entry) { if (((entry != null) ? entry.Definition : null) == (ConfigDefinition)null) { return false; } if (IsHiddenConfigKey(entry.Definition.Key)) { return false; } ConfigDescription description = entry.Description; object[] array = ((description != null) ? description.Tags : null); if (array == null) { return true; } foreach (object obj in array) { if (obj == null) { continue; } if (obj is ConfigurationManagerAttributes { Browsable: var browsable } configurationManagerAttributes) { if (browsable == false) { return false; } if (configurationManagerAttributes.IsAdvanced == true && !ModdedWolfsConfigsPlugin.ShowAdvancedSettings.Value) { return false; } continue; } PropertyInfo property = obj.GetType().GetProperty("Browsable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool?) && (bool?)property.GetValue(obj, null) == false) { return false; } PropertyInfo property2 = obj.GetType().GetProperty("IsAdvanced", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property2 != null && property2.PropertyType == typeof(bool?) && (bool?)property2.GetValue(obj, null) == true && !ModdedWolfsConfigsPlugin.ShowAdvancedSettings.Value) { return false; } } return true; } private static bool SectionHasBinding(DiscoveredSection section) { if (section?.Entries == null) { return false; } for (int i = 0; i < section.Entries.Count; i++) { if (ClientLocalBindings.IsBinding(section.Entries[i])) { return true; } } return false; } private static int GetOrder(ConfigEntryBase entry) { object obj; if (entry == null) { obj = null; } else { ConfigDescription description = entry.Description; obj = ((description != null) ? description.Tags : null); } object[] array = (object[])obj; if (array == null) { return 0; } foreach (object obj2 in array) { if (obj2 is ConfigurationManagerAttributes configurationManagerAttributes && configurationManagerAttributes.Order.HasValue) { return configurationManagerAttributes.Order.Value; } PropertyInfo propertyInfo = obj2?.GetType().GetProperty("Order", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null && propertyInfo.PropertyType == typeof(int?)) { int? num = (int?)propertyInfo.GetValue(obj2, null); if (num.HasValue) { return num.Value; } } FieldInfo fieldInfo = obj2?.GetType().GetField("Order", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null && fieldInfo.FieldType == typeof(int?)) { int? num2 = (int?)fieldInfo.GetValue(obj2); if (num2.HasValue) { return num2.Value; } } } return 0; } internal static string GetDisplayName(ConfigEntryBase entry) { object obj; if (entry == null) { obj = null; } else { ConfigDescription description = entry.Description; obj = ((description != null) ? description.Tags : null); } object[] array = (object[])obj; if (array != null) { for (int i = 0; i < array.Length; i++) { if (array[i] is ConfigurationManagerAttributes configurationManagerAttributes && !string.IsNullOrEmpty(configurationManagerAttributes.DispName)) { return configurationManagerAttributes.DispName; } PropertyInfo propertyInfo = array[i]?.GetType().GetProperty("DispName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null && propertyInfo.PropertyType == typeof(string)) { string text = propertyInfo.GetValue(array[i], null) as string; if (!string.IsNullOrEmpty(text)) { return text; } } FieldInfo fieldInfo = array[i]?.GetType().GetField("DispName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null && fieldInfo.FieldType == typeof(string)) { string text2 = fieldInfo.GetValue(array[i]) as string; if (!string.IsNullOrEmpty(text2)) { return text2; } } } } object obj2; if (entry == null) { obj2 = null; } else { ConfigDefinition definition = entry.Definition; obj2 = ((definition != null) ? definition.Key : null); } if (obj2 == null) { obj2 = string.Empty; } return (string)obj2; } } internal static class ConfigEntryAccess { internal static bool IsReadOnly(ConfigEntryBase entry) { object obj; if (entry == null) { obj = null; } else { ConfigDescription description = entry.Description; obj = ((description != null) ? description.Tags : null); } object[] array = (object[])obj; if (array == null || array.Length == 0) { return false; } bool? flag = null; bool? flag2 = null; foreach (object obj2 in array) { if (obj2 == null) { continue; } if (obj2 is ConfigurationManagerAttributes configurationManagerAttributes) { if (configurationManagerAttributes.ReadOnly.HasValue) { flag = configurationManagerAttributes.ReadOnly; } if (configurationManagerAttributes.IsAdminOnly.HasValue) { flag2 = configurationManagerAttributes.IsAdminOnly; } continue; } bool? nullableBoolProperty = GetNullableBoolProperty(obj2, "ReadOnly"); if (nullableBoolProperty.HasValue) { flag = nullableBoolProperty; } bool? nullableBoolProperty2 = GetNullableBoolProperty(obj2, "IsAdminOnly"); if (nullableBoolProperty2.HasValue) { flag2 = nullableBoolProperty2; } } if (flag.HasValue) { return flag.Value; } return flag2 == true; } internal static bool HidesSettingName(ConfigEntryBase entry) { object obj; if (entry == null) { obj = null; } else { ConfigDescription description = entry.Description; obj = ((description != null) ? description.Tags : null); } object[] array = (object[])obj; if (array == null) { return false; } foreach (object obj2 in array) { if (obj2 != null) { if (obj2 is ConfigurationManagerAttributes configurationManagerAttributes && configurationManagerAttributes.HideSettingName == true) { return true; } if (GetNullableBoolMember(obj2, "HideSettingName") == true) { return true; } } } return false; } private static bool? GetNullableBoolProperty(object tag, string name) { return GetNullableBoolMember(tag, name); } private static bool? GetNullableBoolMember(object tag, string name) { Type type = tag.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool?)) { return (bool?)property.GetValue(tag, null); } FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool?)) { return (bool?)field.GetValue(tag); } return null; } } internal static class GlobalPresetStore { internal const int SlotCount = 5; private const string FileName = "_Global.txt"; private static bool _loaded; private static int _active; private static readonly Dictionary<string, string>[] Slots = new Dictionary<string, string>[6]; private static readonly string[] Names = new string[6]; private static readonly string[] Descs = new string[6]; private static string FilePath => Path.Combine(PresetStore.FolderPath, "_Global.txt"); internal static event Action Changed; internal static int GetActive() { EnsureLoaded(); return _active; } internal static void SetActive(int slot) { EnsureLoaded(); _active = (PresetStore.IsValidSlot(slot) ? slot : 0); WriteAndNotify(); } internal static bool HasSlot(int slot) { EnsureLoaded(); if (PresetStore.IsValidSlot(slot)) { return Slots[slot] != null; } return false; } internal static string GetName(int slot) { EnsureLoaded(); if (!PresetStore.IsValidSlot(slot)) { return null; } return Names[slot]; } internal static string GetDescription(int slot) { EnsureLoaded(); if (!PresetStore.IsValidSlot(slot)) { return null; } return Descs[slot]; } internal static string DisplayName(int slot) { string name = GetName(slot); if (!string.IsNullOrWhiteSpace(name)) { return name; } return "Preset " + slot; } internal static void SetMeta(int slot, string name, string description) { EnsureLoaded(); if (PresetStore.IsValidSlot(slot)) { Names[slot] = PresetStore.CleanMeta(name, 20); Descs[slot] = PresetStore.CleanMeta(description, 120); WriteAndNotify(); } } internal static void Delete(int slot) { EnsureLoaded(); if (PresetStore.IsValidSlot(slot)) { Slots[slot] = null; ConfigEntry<bool> keepGlobalPresetLabel = ModdedWolfsConfigsPlugin.KeepGlobalPresetLabel; if (keepGlobalPresetLabel == null || !keepGlobalPresetLabel.Value) { Names[slot] = null; Descs[slot] = null; } if (_active == slot) { _active = 0; } WriteAndNotify(); ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Deleted global preset {slot}."); } } internal static void Capture(int slot) { EnsureLoaded(); if (!PresetStore.IsValidSlot(slot)) { return; } Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); HashSet<ConfigFile> hashSet = new HashSet<ConfigFile>(); List<DiscoveredPlugin> list = ConfigDiscovery.Discover(); for (int i = 0; i < list.Count; i++) { DiscoveredPlugin plugin = list[i]; foreach (ConfigEntryBase item in PresetStore.EnumerateEntries(plugin)) { try { dictionary[KeyFor(plugin, item)] = item.GetSerializedValue() ?? string.Empty; if (item.ConfigFile != null) { hashSet.Add(item.ConfigFile); } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Global preset capture skipped {item.Definition}: {ex.Message}"); } } } foreach (ConfigFile item2 in hashSet) { try { item2.Save(); } catch (Exception ex2) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to save config: " + ex2.Message)); } } Slots[slot] = dictionary; _active = slot; WriteAndNotify(); ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Saved {dictionary.Count} setting(s) from {list.Count} mod(s) to global preset {slot}."); } internal static void Apply(int slot) { EnsureLoaded(); if (!HasSlot(slot)) { return; } Dictionary<string, string> dictionary = Slots[slot]; Dictionary<ConfigFile, bool> dictionary2 = new Dictionary<ConfigFile, bool>(); int num = 0; try { List<DiscoveredPlugin> list = ConfigDiscovery.Discover(); for (int i = 0; i < list.Count; i++) { DiscoveredPlugin plugin = list[i]; foreach (ConfigEntryBase item in PresetStore.EnumerateEntries(plugin)) { if (!dictionary.TryGetValue(KeyFor(plugin, item), out var value)) { continue; } ConfigFile configFile = item.ConfigFile; if (configFile != null && !dictionary2.ContainsKey(configFile)) { dictionary2[configFile] = configFile.SaveOnConfigSet; configFile.SaveOnConfigSet = false; } try { if (!string.Equals(item.GetSerializedValue(), value, StringComparison.Ordinal)) { item.SetSerializedValue(value); } num++; } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Global preset apply skipped {item.Definition}: {ex.Message}"); } } } } finally { foreach (KeyValuePair<ConfigFile, bool> item2 in dictionary2) { item2.Key.SaveOnConfigSet = item2.Value; try { item2.Key.Save(); } catch (Exception ex2) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to save config: " + ex2.Message)); } ConfigDiscovery.RefreshRuntimeValues(item2.Key); } } _active = slot; WriteAndNotify(); ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Loaded global preset {slot} ({num} setting(s))."); } internal static bool IsModified(int slot) { if (!HasSlot(slot)) { return false; } Dictionary<string, string> dictionary = Slots[slot]; List<DiscoveredPlugin> list = ConfigDiscovery.Discover(); for (int i = 0; i < list.Count; i++) { DiscoveredPlugin plugin = list[i]; foreach (ConfigEntryBase item in PresetStore.EnumerateEntries(plugin)) { if (dictionary.TryGetValue(KeyFor(plugin, item), out var value)) { string a; try { a = item.GetSerializedValue() ?? string.Empty; } catch { continue; } if (!string.Equals(a, value, StringComparison.Ordinal)) { return true; } } } } return false; } private static string KeyFor(DiscoveredPlugin plugin, ConfigEntryBase entry) { return plugin.Guid + "\t" + PresetStore.KeyFor(entry); } private static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; string filePath = FilePath; if (!File.Exists(filePath)) { return; } try { Dictionary<string, string> dictionary = null; string[] array = File.ReadAllLines(filePath, Encoding.UTF8); for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd(new char[1] { '\r' }); if (text.Length == 0) { continue; } if (text.StartsWith("active=", StringComparison.OrdinalIgnoreCase)) { int.TryParse(text.Substring(7), out var result); _active = (PresetStore.IsValidSlot(result) ? result : 0); } else { if (PresetStore.TryParseMetaLine(text, Names, Descs)) { continue; } if (text.StartsWith("[Preset", StringComparison.OrdinalIgnoreCase) && text.EndsWith("]")) { dictionary = null; if (int.TryParse(text.Substring(7, text.Length - 8), out var result2) && PresetStore.IsValidSlot(result2)) { dictionary = new Dictionary<string, string>(StringComparer.Ordinal); Slots[result2] = dictionary; } } else if (dictionary != null) { string[] array2 = text.Split(new char[1] { '\t' }); if (array2.Length == 4) { dictionary[PresetStore.Unescape(array2[0]) + "\t" + PresetStore.Unescape(array2[1]) + "\t" + PresetStore.Unescape(array2[2])] = PresetStore.Unescape(array2[3]); } } } } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to read global presets: " + ex.Message)); } } private static void WriteAndNotify() { Write(); try { GlobalPresetStore.Changed?.Invoke(); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Global preset listener failed: " + ex.Message)); } } private static void Write() { try { string filePath = FilePath; Directory.CreateDirectory(Path.GetDirectoryName(filePath)); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("active=").Append(_active).Append('\n'); PresetStore.AppendMetaLines(stringBuilder, Names, Descs); for (int i = 1; i <= 5; i++) { Dictionary<string, string> dictionary = Slots[i]; if (dictionary == null) { continue; } stringBuilder.Append("[Preset").Append(i).Append("]\n"); foreach (KeyValuePair<string, string> item in dictionary) { string[] array = item.Key.Split(new char[1] { '\t' }, 3); if (array.Length == 3) { stringBuilder.Append(PresetStore.Escape(array[0])).Append('\t').Append(PresetStore.Escape(array[1])) .Append('\t') .Append(PresetStore.Escape(array[2])) .Append('\t') .Append(PresetStore.Escape(item.Value)) .Append('\n'); } } } File.WriteAllText(filePath, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to write global presets: " + ex.Message)); } } } internal static class PresetStore { private sealed class ModPresets { public int Active; public readonly Dictionary<string, string>[] Slots = new Dictionary<string, string>[6]; public readonly string[] Names = new string[6]; public readonly string[] Descs = new string[6]; } internal const int SlotCount = 5; private const string FolderName = "ModdedWolf.ModConfigs.Presets"; internal const int NameMaxLength = 20; internal const int DescriptionMaxLength = 120; private static readonly Dictionary<string, ModPresets> Cache = new Dictionary<string, ModPresets>(StringComparer.OrdinalIgnoreCase); internal static string FolderPath => Path.Combine(Paths.ConfigPath, "ModdedWolf.ModConfigs.Presets"); internal static int GetActive(string guid) { return Load(guid)?.Active ?? 0; } internal static void SetActive(string guid, int slot) { ModPresets modPresets = Load(guid); if (modPresets != null) { modPresets.Active = (IsValidSlot(slot) ? slot : 0); Write(guid, modPresets); } } internal static bool HasSlot(string guid, int slot) { ModPresets modPresets = Load(guid); if (modPresets != null && IsValidSlot(slot)) { return modPresets.Slots[slot] != null; } return false; } internal static string GetName(string guid, int slot) { ModPresets modPresets = Load(guid); if (modPresets == null || !IsValidSlot(slot)) { return null; } return modPresets.Names[slot]; } internal static string GetDescription(string guid, int slot) { ModPresets modPresets = Load(guid); if (modPresets == null || !IsValidSlot(slot)) { return null; } return modPresets.Descs[slot]; } internal static string DisplayName(string guid, int slot) { string name = GetName(guid, slot); if (!string.IsNullOrWhiteSpace(name)) { return name; } return "Preset " + slot; } internal static void SetMeta(string guid, int slot, string name, string description) { ModPresets modPresets = Load(guid); if (modPresets != null && IsValidSlot(slot)) { modPresets.Names[slot] = CleanMeta(name, 20); modPresets.Descs[slot] = CleanMeta(description, 120); Write(guid, modPresets); } } internal static string CleanMeta(string value, int maxLength) { if (string.IsNullOrWhiteSpace(value)) { return null; } string text = value.Replace('\r', ' ').Replace('\n', ' ').Replace('\t', ' ') .Trim(); if (text.Length <= maxLength) { return text; } return text.Substring(0, maxLength); } internal static bool TryParseMetaLine(string line, string[] names, string[] descs) { if (line.IndexOf('\t') >= 0) { return false; } string[] array; int num; if (line.StartsWith("name", StringComparison.OrdinalIgnoreCase)) { array = names; num = 4; } else { if (!line.StartsWith("desc", StringComparison.OrdinalIgnoreCase)) { return false; } array = descs; num = 4; } int num2 = line.IndexOf('='); if (num2 <= num || !int.TryParse(line.Substring(num, num2 - num), out var result) || !IsValidSlot(result)) { return false; } string text = Unescape(line.Substring(num2 + 1)); array[result] = ((text.Length > 0) ? text : null); return true; } internal static void AppendMetaLines(StringBuilder sb, string[] names, string[] descs) { for (int i = 1; i <= 5; i++) { if (!string.IsNullOrEmpty(names[i])) { sb.Append("name").Append(i).Append('=') .Append(Escape(names[i])) .Append('\n'); } if (!string.IsNullOrEmpty(descs[i])) { sb.Append("desc").Append(i).Append('=') .Append(Escape(descs[i])) .Append('\n'); } } } internal static void Delete(string guid, int slot) { ModPresets modPresets = Load(guid); if (modPresets != null && IsValidSlot(slot)) { modPresets.Slots[slot] = null; if (modPresets.Active == slot) { modPresets.Active = 0; } Write(guid, modPresets); ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Deleted preset {slot} for {guid}."); } } internal static void Capture(DiscoveredPlugin plugin, int slot) { if (plugin == null || !IsValidSlot(slot)) { return; } ModPresets modPresets = Load(plugin.Guid); if (modPresets == null) { return; } Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); foreach (ConfigEntryBase item in EnumerateEntries(plugin)) { try { dictionary[KeyFor(item)] = item.GetSerializedValue() ?? string.Empty; } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Preset capture skipped {item.Definition}: {ex.Message}"); } } modPresets.Slots[slot] = dictionary; modPresets.Active = slot; Write(plugin.Guid, modPresets); ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Saved {dictionary.Count} setting(s) to preset {slot} for {plugin.Name}."); } internal static void Apply(DiscoveredPlugin plugin, int slot) { if (plugin == null || !IsValidSlot(slot)) { return; } ModPresets modPresets = Load(plugin.Guid); Dictionary<string, string> dictionary = ((modPresets != null) ? modPresets.Slots[slot] : null); if (dictionary == null) { return; } Dictionary<ConfigFile, bool> dictionary2 = new Dictionary<ConfigFile, bool>(); int num = 0; try { foreach (ConfigEntryBase item in EnumerateEntries(plugin)) { if (!dictionary.TryGetValue(KeyFor(item), out var value)) { continue; } ConfigFile configFile = item.ConfigFile; if (configFile != null && !dictionary2.ContainsKey(configFile)) { dictionary2[configFile] = configFile.SaveOnConfigSet; configFile.SaveOnConfigSet = false; } try { if (!string.Equals(item.GetSerializedValue(), value, StringComparison.Ordinal)) { item.SetSerializedValue(value); } num++; } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Preset apply skipped {item.Definition}: {ex.Message}"); } } } finally { foreach (KeyValuePair<ConfigFile, bool> item2 in dictionary2) { item2.Key.SaveOnConfigSet = item2.Value; try { item2.Key.Save(); } catch (Exception ex2) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to save config: " + ex2.Message)); } ConfigDiscovery.RefreshRuntimeValues(item2.Key); } } modPresets.Active = slot; Write(plugin.Guid, modPresets); ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Loaded preset {slot} ({num} setting(s)) for {plugin.Name}."); } internal static bool IsModified(DiscoveredPlugin plugin, int slot) { if (plugin == null || !IsValidSlot(slot)) { return false; } ModPresets modPresets = Load(plugin.Guid); Dictionary<string, string> dictionary = ((modPresets != null) ? modPresets.Slots[slot] : null); if (dictionary == null) { return false; } foreach (ConfigEntryBase item in EnumerateEntries(plugin)) { if (dictionary.TryGetValue(KeyFor(item), out var value)) { string a; try { a = item.GetSerializedValue() ?? string.Empty; } catch { continue; } if (!string.Equals(a, value, StringComparison.Ordinal)) { return true; } } } return false; } internal static IEnumerable<ConfigEntryBase> EnumerateEntries(DiscoveredPlugin plugin) { for (int s = 0; s < plugin.Sections.Count; s++) { List<ConfigEntryBase> entries = plugin.Sections[s].Entries; for (int e = 0; e < entries.Count; e++) { ConfigEntryBase val = entries[e]; if (!(((val != null) ? val.Definition : null) == (ConfigDefinition)null) && !ConfigDiscovery.IsHiddenConfigKey(val.Definition.Key) && !ConfigEntryAccess.IsReadOnly(val)) { yield return val; } } } } internal static bool IsValidSlot(int slot) { if (slot >= 1) { return slot <= 5; } return false; } internal static string KeyFor(ConfigEntryBase entry) { return (entry.Definition.Section ?? string.Empty) + "\t" + entry.Definition.Key; } private static string PathFor(string guid) { StringBuilder stringBuilder = new StringBuilder(guid.Length); char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char c in guid) { stringBuilder.Append((Array.IndexOf(invalidFileNameChars, c) >= 0) ? '_' : c); } return Path.Combine(FolderPath, stringBuilder?.ToString() + ".txt"); } private static ModPresets Load(string guid) { if (string.IsNullOrEmpty(guid)) { return null; } if (Cache.TryGetValue(guid, out var value)) { return value; } ModPresets modPresets = new ModPresets(); Cache[guid] = modPresets; string path = PathFor(guid); if (!File.Exists(path)) { return modPresets; } try { Dictionary<string, string> dictionary = null; string[] array = File.ReadAllLines(path, Encoding.UTF8); for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd(new char[1] { '\r' }); if (text.Length == 0) { continue; } if (text.StartsWith("active=", StringComparison.OrdinalIgnoreCase)) { int.TryParse(text.Substring(7), out var result); modPresets.Active = (IsValidSlot(result) ? result : 0); } else { if (TryParseMetaLine(text, modPresets.Names, modPresets.Descs)) { continue; } if (text.StartsWith("[Preset", StringComparison.OrdinalIgnoreCase) && text.EndsWith("]")) { dictionary = null; if (int.TryParse(text.Substring(7, text.Length - 8), out var result2) && IsValidSlot(result2)) { dictionary = new Dictionary<string, string>(StringComparer.Ordinal); modPresets.Slots[result2] = dictionary; } } else if (dictionary != null) { string[] array2 = text.Split(new char[1] { '\t' }); if (array2.Length == 3) { dictionary[Unescape(array2[0]) + "\t" + Unescape(array2[1])] = Unescape(array2[2]); } } } } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to read presets for " + guid + ": " + ex.Message)); } return modPresets; } private static void Write(string guid, ModPresets presets) { try { string path = PathFor(guid); Directory.CreateDirectory(Path.GetDirectoryName(path)); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("active=").Append(presets.Active).Append('\n'); AppendMetaLines(stringBuilder, presets.Names, presets.Descs); for (int i = 1; i <= 5; i++) { Dictionary<string, string> dictionary = presets.Slots[i]; if (dictionary == null) { continue; } stringBuilder.Append("[Preset").Append(i).Append("]\n"); foreach (KeyValuePair<string, string> item in dictionary) { int num = item.Key.IndexOf('\t'); string value = ((num >= 0) ? item.Key.Substring(0, num) : string.Empty); string value2 = ((num >= 0) ? item.Key.Substring(num + 1) : item.Key); stringBuilder.Append(Escape(value)).Append('\t').Append(Escape(value2)) .Append('\t') .Append(Escape(item.Value)) .Append('\n'); } } File.WriteAllText(path, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to write presets for " + guid + ": " + ex.Message)); } } internal static string Escape(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } return value.Replace("\\", "\\\\").Replace("\t", "\\t").Replace("\r", "\\r") .Replace("\n", "\\n"); } internal static string Unescape(string value) { if (string.IsNullOrEmpty(value) || value.IndexOf('\\') < 0) { return value ?? string.Empty; } StringBuilder stringBuilder = new StringBuilder(value.Length); for (int i = 0; i < value.Length; i++) { char c = value[i]; if (c != '\\' || i + 1 >= value.Length) { stringBuilder.Append(c); continue; } char c2 = value[++i]; switch (c2) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; default: stringBuilder.Append(c2); break; } } return stringBuilder.ToString(); } } internal static class SessionSnapshot { private static readonly Dictionary<ConfigEntryBase, string> Values = new Dictionary<ConfigEntryBase, string>(); internal static void Begin() { Values.Clear(); List<DiscoveredPlugin> list = ConfigDiscovery.Discover(); for (int i = 0; i < list.Count; i++) { foreach (ConfigEntryBase item in PresetStore.EnumerateEntries(list[i])) { try { Values[item] = item.GetSerializedValue() ?? string.Empty; } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Snapshot skipped {item.Definition}: {ex.Message}"); } } } } internal static void Commit() { Values.Clear(); } internal static int Revert() { if (Values.Count == 0) { return 0; } Dictionary<ConfigFile, bool> dictionary = new Dictionary<ConfigFile, bool>(); int num = 0; try { foreach (KeyValuePair<ConfigEntryBase, string> value in Values) { ConfigEntryBase key = value.Key; if (key == null || ConfigEntryAccess.IsReadOnly(key)) { continue; } try { if (!string.Equals(key.GetSerializedValue(), value.Value, StringComparison.Ordinal)) { ConfigFile configFile = key.ConfigFile; if (configFile != null && !dictionary.ContainsKey(configFile)) { dictionary[configFile] = configFile.SaveOnConfigSet; configFile.SaveOnConfigSet = false; } key.SetSerializedValue(value.Value); num++; } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Cancel could not restore {key.Definition}: {ex.Message}"); } } } finally { foreach (KeyValuePair<ConfigFile, bool> item in dictionary) { item.Key.SaveOnConfigSet = item.Value; try { item.Key.Save(); } catch (Exception ex2) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to save config: " + ex2.Message)); } ConfigDiscovery.RefreshRuntimeValues(item.Key); } Values.Clear(); } if (num > 0) { ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Cancel restored {num} setting(s)."); } return num; } } internal static class PauseMenuButton { [CompilerGenerated] private static class <>O { public static UnityAction <0>__Open; } internal static void Refresh() { try { bool flag = ModdedWolfsConfigsPlugin.ShowMainMenuButton == null || ModdedWolfsConfigsPlugin.ShowMainMenuButton.Value; bool flag2 = ModdedWolfsConfigsPlugin.ShowPauseMenuButton == null || ModdedWolfsConfigsPlugin.ShowPauseMenuButton.Value; if ((Object)(object)FejdStartup.instance != (Object)null) { Transform val = (((Object)(object)FejdStartup.instance.m_menuList != (Object)null) ? FejdStartup.instance.m_menuList.transform : null); SetupFromHierarchy(FindMenuEntries(val), flag); if ((Object)(object)val != (Object)null) { FejdStartup.instance.m_menuButtons = ((Component)val).GetComponentsInChildren<Button>(false); } if (!flag) { HideNamedUnder(((Component)FejdStartup.instance).transform); } } if ((Object)(object)Menu.instance != (Object)null) { SetupPauseMenu(flag2); if (!flag2) { HideNamedUnder(((Component)Menu.instance).transform); } } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to refresh menu button: " + ex.Message)); } } internal static bool IsModConfigsControlActive() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)EventSystem.current == (Object)null) { return false; } if (IsNamedModButton(EventSystem.current.currentSelectedGameObject)) { return true; } if (Input.GetMouseButton(0) || Input.GetMouseButtonUp(0)) { PointerEventData val = new PointerEventData(EventSystem.current) { position = Vector2.op_Implicit(Input.mousePosition) }; List<RaycastResult> list = new List<RaycastResult>(); EventSystem.current.RaycastAll(val, list); for (int i = 0; i < list.Count; i++) { RaycastResult val2 = list[i]; if (IsNamedModButton(((RaycastResult)(ref val2)).gameObject)) { return true; } } } return false; } private static bool IsNamedModButton(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } Transform val = go.transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name == "ModdedWolfsConfigs") { return true; } val = val.parent; } return false; } private static void SetupPauseMenu(bool show) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) Menu instance = Menu.instance; if ((Object)(object)instance == (Object)null) { return; } Button val = instance.m_settingsButton; Transform val2 = null; if ((Object)(object)val != (Object)null) { val2 = ((Component)val).transform.parent; } if ((Object)(object)val2 == (Object)null && (Object)(object)instance.menuEntriesParent != (Object)null) { val2 = (Transform)(object)instance.menuEntriesParent; } if ((Object)(object)val2 == (Object)null) { val2 = FindMenuEntries(instance.m_menuDialog); } if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null) { val = FindSettingsButtonUnder(val2); } if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { Button val3 = EnsureModButton(val2, val); ApplyLabel(((Component)val3).gameObject); RewireClick(val3); ((Component)val3).gameObject.SetActive(show); object obj; if (!((Object)(object)instance.m_logoutButton != (Object)null)) { Navigation navigation = ((Selectable)val).navigation; Selectable selectOnDown = ((Navigation)(ref navigation)).selectOnDown; obj = ((selectOnDown is Button) ? selectOnDown : null); } else { obj = instance.m_logoutButton; } Button nextButton = (Button)obj; WireNavigation(val, val3, nextButton, show); } } private static void SetupFromHierarchy(Transform menuEntries, bool show) { //IL_0041: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)menuEntries == (Object)null) { return; } Button val = FindSettingsButtonUnder(menuEntries); if (!((Object)(object)val == (Object)null)) { Button val2 = EnsureModButton(menuEntries, val); ApplyLabel(((Component)val2).gameObject); RewireClick(val2); ((Component)val2).gameObject.SetActive(show); Navigation navigation = ((Selectable)val).navigation; Selectable selectOnDown = ((Navigation)(ref navigation)).selectOnDown; Button val3 = (Button)(object)((selectOnDown is Button) ? selectOnDown : null); if ((Object)(object)val3 != (Object)null && ((Object)val3).name == "ModdedWolfsConfigs") { navigation = ((Selectable)val3).navigation; Selectable selectOnDown2 = ((Navigation)(ref navigation)).selectOnDown; val3 = (Button)(object)((selectOnDown2 is Button) ? selectOnDown2 : null); } WireNavigation(val, val2, val3, show); } } private static Button EnsureModButton(Transform parent, Button settingsButton) { Transform val = parent.Find("ModdedWolfsConfigs"); GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); if ((Object)(object)val2 == (Object)null) { val2 = Object.Instantiate<GameObject>(((Component)settingsButton).gameObject, parent); ((Object)val2).name = "ModdedWolfsConfigs"; val2.transform.SetSiblingIndex(((Component)settingsButton).transform.GetSiblingIndex() + 1); } Button component = val2.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Cloned Mod Configs control is missing a Button."); } return component; } private static void RewireClick(Button button) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_002b: 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_0036: Expected O, but got Unknown if ((Object)(object)button == (Object)null) { return; } button.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = button.onClick; object obj = <>O.<0>__Open; if (obj == null) { UnityAction val = ConfigPanelOpener.Open; <>O.<0>__Open = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); EventTrigger[] componentsInChildren = ((Component)button).GetComponentsInChildren<EventTrigger>(true); foreach (EventTrigger val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2.triggers != null) { val2.triggers.RemoveAll((Entry entry) => entry != null && ((int)entry.eventID == 4 || (int)entry.eventID == 15)); } } } private static void ApplyLabel(GameObject menuButton) { TMP_Text componentInChildren = menuButton.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = "Mod Configs"; } Text componentInChildren2 = menuButton.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.text = "Mod Configs"; } } private static Button FindSettingsButtonUnder(Transform menuEntries) { Transform val = menuEntries.Find("Settings"); if ((Object)(object)val == (Object)null) { for (int i = 0; i < menuEntries.childCount; i++) { Transform child = menuEntries.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name.IndexOf("Settings", StringComparison.OrdinalIgnoreCase) >= 0 && ((Object)child).name != "ModdedWolfsConfigs") { val = child; break; } } } if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent<Button>(); } private static Transform FindMenuEntries(Transform root) { if ((Object)(object)root == (Object)null) { return null; } Transform val = root.Find("MenuEntries"); if ((Object)(object)val != (Object)null) { return val; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "MenuEntries") { return componentsInChildren[i]; } } return null; } private static void HideNamedUnder(Transform root) { if ((Object)(object)root == (Object)null) { return; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "ModdedWolfsConfigs") { ((Component)componentsInChildren[i]).gameObject.SetActive(false); } } } private static void WireNavigation(Button settingsButton, Button modButton, Button nextButton, bool show) { //IL_0044: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_00c6: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)settingsButton == (Object)null || (Object)(object)modButton == (Object)null) { return; } if ((Object)(object)nextButton != (Object)null && ((Object)nextButton).name == "ModdedWolfsConfigs") { Navigation navigation = ((Selectable)nextButton).navigation; Selectable selectOnDown = ((Navigation)(ref navigation)).selectOnDown; nextButton = (Button)(object)((selectOnDown is Button) ? selectOnDown : null); } Navigation navigation2 = ((Selectable)settingsButton).navigation; Navigation navigation3 = ((Selectable)modButton).navigation; if (show) { ((Navigation)(ref navigation2)).selectOnDown = (Selectable)(object)modButton; ((Navigation)(ref navigation3)).selectOnUp = (Selectable)(object)settingsButton; ((Navigation)(ref navigation3)).selectOnDown = (Selectable)(object)nextButton; ((Navigation)(ref navigation3)).mode = (Mode)4; ((Selectable)modButton).navigation = navigation3; if ((Object)(object)nextButton != (Object)null) { Navigation navigation4 = ((Selectable)nextButton).navigation; ((Navigation)(ref navigation4)).selectOnUp = (Selectable)(object)modButton; ((Selectable)nextButton).navigation = navigation4; } } else if ((Object)(object)nextButton != (Object)null) { ((Navigation)(ref navigation2)).selectOnDown = (Selectable)(object)nextButton; Navigation navigation5 = ((Selectable)nextButton).navigation; ((Navigation)(ref navigation5)).selectOnUp = (Selectable)(object)settingsButton; ((Selectable)nextButton).navigation = navigation5; } ((Selectable)settingsButton).navigation = navigation2; } } [BepInPlugin("ModdedWolf.ModConfigs", "Mod Configs", "1.1.1")] public class ModdedWolfsConfigsPlugin : BaseUnityPlugin { public const string GUID = "ModdedWolf.ModConfigs"; private const string LegacyGuid = "ModdedWolf.ModdedWolfsConfigs"; public const string NAME = "Mod Configs"; public const string VERSION = "1.1.1"; internal const string MenuButtonName = "ModdedWolfsConfigs"; internal const string MenuButtonCaption = "Mod Configs"; internal const string PanelTitle = "Mod Configs"; internal static ConfigEntry<bool> ShowMainMenuButton; internal static ConfigEntry<bool> ShowPauseMenuButton; internal static ConfigEntry<bool> ShowAdvancedSettings; internal static ConfigEntry<bool> HideSelfFromList; internal static ConfigEntry<bool> RememberLastMod; internal static ConfigEntry<bool> KeepGlobalPresetLabel; internal const string LastSelectedModGuidKey = "LastSelectedModGuid"; internal static ConfigEntry<string> LastSelectedModGuid; private Harmony _harmony; internal static ModdedWolfsConfigsPlugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; TryMigrateLegacyConfigFile(); ShowMainMenuButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMainMenuButton", false, "Show Mod Configs on the main menu (title screen)."); ShowPauseMenuButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowPauseMenuButton", true, "Show Mod Configs on the in-game pause menu."); TryMigrateLegacyShowMenuButton(); ShowAdvancedSettings = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowAdvancedSettings", true, "Show settings marked as advanced (ConfigurationManagerAttributes.IsAdvanced)."); HideSelfFromList = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideSelfFromList", false, "Hide this mod's own settings from the in-game config panel."); RememberLastMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RememberLastMod", true, "When enabled, reopen Mod Configs on the last mod you had selected."); KeepGlobalPresetLabel = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepGlobalPresetLabel", false, "When deleting a global preset, keep its name and description."); LastSelectedModGuid = ((BaseUnityPlugin)this).Config.Bind<string>("General", "LastSelectedModGuid", "", new ConfigDescription("GUID of the last mod opened in Mod Configs (remembered between sessions).", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); ShowMainMenuButton.SettingChanged += delegate { PauseMenuButton.Refresh(); }; ShowPauseMenuButton.SettingChanged += delegate { PauseMenuButton.Refresh(); }; ShowAdvancedSettings.SettingChanged += delegate { ConfigDiscovery.InvalidateCache(); }; HideSelfFromList.SettingChanged += delegate { ConfigDiscovery.InvalidateCache(); }; ConfigPanelOpener.DiscardPool(); _harmony = new Harmony("ModdedWolf.ModConfigs"); _harmony.PatchAll(); Log.LogInfo((object)"Mod Configs v1.1.1 loaded (client configs)."); } private void TryMigrateLegacyConfigFile() { try { string configPath = Paths.ConfigPath; string text = Path.Combine(configPath, "ModdedWolf.ModConfigs.cfg"); string text2 = Path.Combine(configPath, "ModdedWolf.ModdedWolfsConfigs.cfg"); if (File.Exists(text2) && !File.Exists(text)) { File.Copy(text2, text); Log.LogInfo((object)"Migrated config from ModdedWolf.ModdedWolfsConfigs.cfg to ModdedWolf.ModConfigs.cfg"); } } catch (Exception ex) { Log.LogWarning((object)("Legacy config migration failed: " + ex.Message)); } } private void TryMigrateLegacyShowMenuButton() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown try { ConfigDefinition val = new ConfigDefinition("General", "ShowMenuButton"); if (((BaseUnityPlugin)this).Config.ContainsKey(val)) { if (!((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMenuButton", true, "Deprecated. Use ShowMainMenuButton / ShowPauseMenuButton.").Value) { ShowMainMenuButton.Value = false; ShowPauseMenuButton.Value = true; } ((BaseUnityPlugin)this).Config.Remove(val); ((BaseUnityPlugin)this).Config.Save(); } } catch { } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(Menu), "Start")] internal static class Menu_Start_Patch { private static void Postfix() { PauseMenuButton.Refresh(); } } [HarmonyPatch(typeof(Menu), "UpdateNavigation")] internal static class Menu_UpdateNavigation_Patch { private static void Postfix() { PauseMenuButton.Refresh(); } } [HarmonyPatch(typeof(Menu), "OnSettings")] internal static class Menu_OnSettings_Patch { private static bool Prefix() { if (!PauseMenuButton.IsModConfigsControlActive()) { return true; } ConfigPanelOpener.Open(); return false; } } [HarmonyPatch(typeof(FejdStartup), "Start")] internal static class FejdStartup_Start_Patch { private static void Postfix() { PauseMenuButton.Refresh(); } } [HarmonyPatch(typeof(FejdStartup), "SetupGui")] internal static class FejdStartup_SetupGui_Patch { private static void Postfix() { PauseMenuButton.Refresh(); } } [HarmonyPatch(typeof(Settings), "OnDestroy")] internal static class Settings_OnDestroy_Patch { private static void Postfix(Settings __instance) { ConfigPanelOpener.ForgetInstance(__instance); ModConfigPanel.ForgetInitialized(__instance); PauseMenuButton.Refresh(); } } internal static class SettingsConversionPatches { [HarmonyPatch(typeof(Settings), "Awake")] internal static class SettingsAwakePatch { private static void Prefix(Settings __instance) { if (ConfigPanelOpener.IsOpening) { ConfigPanelOpener.MarkInstance(__instance); } } private static void Postfix(Settings __instance) { if (ShouldConvert(__instance)) { ModConfigPanel.ConvertSettingsInstance(__instance); ModConfigPanel.EnforceConvertedLayout(__instance); } } } [HarmonyPatch(typeof(Settings), "OnInputLayoutChanged")] internal static class SettingsInputLayoutPatch { private static void Postfix(Settings __instance) { if (!ShouldConvert(__instance) || __instance.m_tabKeyHints == null) { return; } for (int i = 0; i < __instance.m_tabKeyHints.Length; i++) { if ((Object)(object)__instance.m_tabKeyHints[i] != (Object)null) { __instance.m_tabKeyHints[i].SetActive(false); } } } } [HarmonyPatch(typeof(Settings), "InitializeTabs")] internal static class SettingsInitializeTabsPatch { private static bool Prefix(Settings __instance) { if (!ShouldConvert(__instance)) { return true; } ConfigPanelOpener.MarkInstance(__instance); ModConfigPanel.ConvertSettingsInstance(__instance); ModConfigPanel.EnforceConvertedLayout(__instance); return false; } } [HarmonyPatch(typeof(Settings), "OnBack")] internal static class SettingsOnBackPatch { private static bool Prefix(Settings __instance) { if (ConfigPanelOpener.IsOurInstance(__instance) && (KeybindCapture.TryCancelListen() || KeybindCapture.HandledBackThisFrame || KeybindCapture.CommittedThisFrame || ModConfigTab.BackHandledThisFrame)) { return false; } if (ConfigPanelOpener.IsOurInstance(__instance) && ModPicker.TryCloseOpenList()) { return false; } if (ConfigPanelOpener.IsOurInstance(__instance) && PresetEditDialog.IsOpen) { PresetEditDialog.Close(); return false; } if (ConfigPanelOpener.IsOurInstance(__instance) && ModConfigTab.TryConsumeBack()) { return false; } if (ConfigPanelOpener.IsOurInstance(__instance)) { try { if (SessionSnapshot.Revert() > 0) { ModConfigTab.MarkOpenInstanceStale(); } } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Cancel failed to restore settings: " + ex.Message)); } } if (ConfigPanelOpener.SoftClose(__instance)) { return false; } return HandleCloseIfBroken(__instance); } } [HarmonyPatch(typeof(Settings), "OnOk")] internal static class SettingsOnOkPatch { private static bool Prefix(Settings __instance) { if (ConfigPanelOpener.IsOurInstance(__instance)) { if (KeybindCapture.IsListening || KeybindCapture.CommittedThisFrame || PresetEditDialog.IsOpen || ModPicker.IsAnyOpen) { return false; } SessionSnapshot.Commit(); } if (ConfigPanelOpener.SoftClose(__instance)) { return false; } return HandleCloseIfBroken(__instance); } } private static bool ShouldConvert(Settings settings) { if (!ConfigPanelOpener.IsOpening) { return ConfigPanelOpener.IsOurInstance(settings); } return true; } private static bool HandleCloseIfBroken(Settings settings) { if (!ConfigPanelOpener.IsOurInstance(settings)) { return true; } List<ISettingsTab> settingsTabs = settings.SettingsTabs; if (settingsTabs != null && settingsTabs.Count > 0) { return true; } ForceClose(settings); return false; } private static void ForceClose(Settings settings) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)settings == (Object)null) { return; } try { if ((Object)(object)Menu.instance != (Object)null && (Object)(object)Menu.instance.m_settingsInstance == (Object)(object)((Component)settings).gameObject) { Menu.instance.m_settingsInstance = null; Menu.instance.m_closeMenuState = (CloseMenuState)2; } Object.Destroy((Object)(object)((Component)settings).gameObject); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to force-close Mod Configs: " + ex.Message)); } } } internal static class ConfigPanelOpener { private static readonly HashSet<int> PendingInstanceIds = new HashSet<int>(); private static readonly FieldInfo SettingsInstanceField = typeof(Settings).GetField("m_instance", BindingFlags.Static | BindingFlags.NonPublic); private static Settings _pooledSettings; private static GameObject _pooledGo; internal static bool IsOpening { get; private set; } internal static void MarkInstance(Settings settings) { if (!((Object)(object)settings == (Object)null)) { PendingInstanceIds.Add(((Object)settings).GetInstanceID()); } } internal static bool IsOurInstance(Settings settings) { if ((Object)(object)settings == (Object)null) { return false; } return PendingInstanceIds.Contains(((Object)settings).GetInstanceID()); } internal static void ForgetInstance(Settings settings) { if (!((Object)(object)settings == (Object)null)) { PendingInstanceIds.Remove(((Object)settings).GetInstanceID()); if ((Object)(object)_pooledSettings != (Object)null && _pooledSettings == settings) { _pooledSettings = null; _pooledGo = null; } } } internal static void Open() { try { if ((Object)(object)Settings.instance != (Object)null || TryOpenPooled()) { return; } GameObject val = FindSettingsPrefab(); if ((Object)(object)val == (Object)null) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)"Could not find Settings prefab (Menu / FejdStartup). Cannot open config panel."); return; } Transform val2 = null; if ((Object)(object)Menu.instance != (Object)null) { val2 = ((Component)Menu.instance).transform; } else if ((Object)(object)FejdStartup.instance != (Object)null) { val2 = ((Component)FejdStartup.instance).transform; } IsOpening = true; GameObject val3 = Object.Instantiate<GameObject>(val, val2); IsOpening = false; Settings val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<Settings>() : null); if ((Object)(object)val4 != (Object)null) { MarkInstance(val4); RememberPool(val4); ModConfigPanel.ConvertSettingsInstance(val4); ModConfigPanel.EnforceConvertedLayout(val4); } BindMenuState(val3); ModdedWolfsConfigsPlugin.Log.LogInfo((object)"Opened ModdedWolf's Configs panel."); } catch (Exception arg) { IsOpening = false; ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Failed to open config panel: {arg}"); } } internal static bool SoftClose(Settings settings) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)settings == (Object)null || !IsOurInstance(settings)) { return false; } try { RememberPool(settings); if ((Object)(object)Menu.instance != (Object)null && (Object)(object)Menu.instance.m_settingsInstance == (Object)(object)((Component)settings).gameObject) { Menu.instance.m_settingsInstance = null; Menu.instance.m_closeMenuState = (CloseMenuState)2; } ClearSettingsSingleton(settings); ((Component)settings).gameObject.SetActive(false); PauseMenuButton.Refresh(); ModdedWolfsConfigsPlugin.Log.LogInfo((object)"Soft-closed ModdedWolf's Configs panel (pooled)."); return true; } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Soft-close failed: " + ex.Message)); return false; } } private static bool TryOpenPooled() { if ((Object)(object)_pooledSettings == (Object)null || (Object)(object)_pooledGo == (Object)null) { return false; } if (!Object.op_Implicit((Object)(object)_pooledSettings)) { _pooledSettings = null; _pooledGo = null; return false; } MarkInstance(_pooledSettings); if (_pooledGo.activeSelf) { _pooledGo.SetActive(false); } SetSettingsSingleton(_pooledSettings); ModConfigPanel.PreparePooledReopen(_pooledSettings); _pooledGo.SetActive(true); ModConfigPanel.WirePooledNavigation(_pooledSettings); BindMenuState(_pooledGo); ModdedWolfsConfigsPlugin.Log.LogInfo((object)"Reopened pooled ModdedWolf's Configs panel."); return true; } internal static void DiscardPool() { if ((Object)(object)_pooledGo != (Object)null) { try { if ((Object)(object)_pooledSettings != (Object)null) { ForgetInstance(_pooledSettings); ModConfigPanel.ForgetInitialized(_pooledSettings); } Object.Destroy((Object)(object)_pooledGo); } catch (Exception ex) { ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to discard pooled panel: " + ex.Message)); } } _pooledSettings = null; _pooledGo = null; } private static void RememberPool(Settings settings) { if (!((Object)(object)settings == (Object)null)) { _pooledSettings = settings; _pooledGo = ((Component)settings).gameObject; } } private static void BindMenuState(GameObject instance) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Menu.instance != (Object)null && (Object)(object)instance != (Object)null) { Menu.instance.m_settingsInstance = instance; Menu.instance.m_closeMenuState = (CloseMenuState)0; } } private static void SetSettingsSingleton(Settings settings) { if (SettingsInstanceField != null) { SettingsInstanceField.SetValue(null, settings); } } private static void ClearSettingsSingleton(Settings settings) { if (!(SettingsInstanceField == null)) { object? value = SettingsInstanceField.GetValue(null); Settings val = (Settings)((value is Settings) ? value : null); if ((Object)(object)val == (Object)null || val == settings) { SettingsInstanceField.SetValue(null, null); } } } private static GameObject FindSettingsPrefab() { if ((Object)(object)Menu.instance != (Object)null && (Object)(object)Menu.instance.m_settingsPrefab != (Object)null) { return Menu.instance.m_settingsPrefab; } if ((Object)(object)FejdStartup.instance != (Object)null && (Object)(object)FejdStartup.instance.m_settingsPrefab != (Object)null) { return FejdStartup.instance.m_settingsPrefab; } return null; } } internal static class GamepadSupport { private const string ButtonY = "JoyButtonY"; private const string ButtonX = "JoyButtonX"; private static bool _footerLogged; private static readonly Vector3[] CornerBuffer = (Vector3[])(object)new Vector3[4]; internal static string RenameButton { get; private set; } = "JoyButtonY"; internal static bool IsActive { get { try { return ZInput.IsGamepadActive(); } catch { return false; } } } internal static bool GetButtonDown(string name) { try { return ZInput.GetButtonDown(name); } catch { return false; } } internal static void Select(Selectable selectable) { if (!((Object)(object)selectable == (Object)null) && ((Behaviour)selectable).isActiveAndEnabled && !((Object)(object)EventSystem.current == (Object)null)) { EventSystem.current.SetSelectedGameObject(((Component)selectable).gameObject); } } internal static bool IsSelectedUnder(Transform root) { GameObject val = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null); if ((Object)(object)val != (Object)null && (Object)(object)root != (Object)null) { return val.transform.IsChildOf(root); } return false; } internal static void LinkVertical(IList<Selectable> items) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (items == null) { return; } List<Selectable> list = new List<Selectable>(items.Count); for (int i = 0; i < items.Count; i++) { if ((Object)(object)items[i] != (Object)null && ((Component)items[i]).gameObject.activeInHierarchy && items[i].interactable) { list.Add(items[i]); } } for (int j = 0; j < list.Count; j++) { Navigation val = default(Navigation); ((Navigation)(ref val)).mode = (Mode)4; ((Navigation)(ref val)).selectOnUp = ((j > 0) ? list[j - 1] : null); ((Navigation)(ref val)).selectOnDown = ((j < list.Count - 1) ? list[j + 1] : null); Navigation navigation = val; list[j].navigation = navigation; } } internal static void SetNavigationNone(Selectable selectable) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)selectable == (Object)null)) { Navigation navigation = selectable.navigation; ((Navigation)(ref navigation)).mode = (Mode)0; selectable.navigation = navigation; } } internal static void SetExplicit(Selectable selectable, Selectable up, Selectable down, Selectable left, Selectable right) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)selectable == (Object)null)) { Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)4; ((Navigation)(ref navigation)).selectOnUp = up; ((Navigation)(ref navigation)).selectOnDown = down; ((Navigation)(ref navigation)).selectOnLeft = left; ((Navigation)(ref navigation)).selectOnRight = right; selectable.navigation = navigation; } } internal static Vector2 Center(Selectable selectable) { //IL_0009: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_002f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)selectable == (Object)null) { return Vector2.zero; } Transform transform = ((Component)selectable).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val == (Object)null) { return Vector2.op_Implicit(((Component)selectable).transform.position); } val.GetWorldCorners(CornerBuffer); return Vector2.op_Implicit((CornerBuffer[0] + CornerBuffer[2]) * 0.5f); } internal static Selectable Closest(IList<Selectable> options, Selectable from, bool matchVertical) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) if ((Object)(object)from == (Object)null || options == null || options.Count == 0) { return null; } Vector2 val = Center(from); Selectable result = null; float num = float.MaxValue; for (int i = 0; i < options.Count; i++) { Selectable val2 = options[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)from)) { Vector2 val3 = Center(val2); float num2 = (matchVertical ? Mathf.Abs(val3.y - val.y) : Mathf.Abs(val3.x - val.x)); if (num2 < num) { num = num2; result = val2; } } } return result; } internal static void ConfigureFromFooter(Settings settings) { if (!((Object)(object)settings == (Object)null)) { string text = FooterKey(settings.m_backButton); string text2 = FooterKey(settings.m_okButton); RenameButton = ((text2 == "JoyButtonY" || text == "JoyButtonY") ? "JoyButtonX" : "JoyButtonY"); if (!_footerLogged) { _footerLogged = true; ModdedWolfsConfigsPlugin.Log.LogInfo((object)("Gamepad footer keys: back='" + (text ?? "-") + "', ok='" + (text2 ?? "-") + "'; rename uses " + RenameButton + ".")); } } } private static string FooterKey(Button button) { if ((Object)(object)button == (Object)null) { return null; } UIGamePad componentInChildren = ((Component)button).GetComponentInChildren<UIGamePad>(true); if (!((Object)(object)componentInChildren != (Object)null) || string.IsNullOrEmpty(componentInChildren.m_zinputKey)) { return null; } return componentInChildren.m_zinputKey; } } internal sealed class ScrollToSelection : MonoBehaviour { private const float Padding = 12f; private ScrollRect _scroll; internal static void Attach(ScrollRect scroll) { if (!((Object)(object)scroll == (Object)null)) { (((Component)scroll).GetComponent<ScrollToSelection>() ?? ((Component)scroll).gameObject.AddComponent<ScrollToSelection>())._scroll = scroll; } } private void LateUpdate() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_scroll == (Object)null || (Object)(object)_scroll.content == (Object)null || (Object)(object)EventSystem.current == (Object)null || !GamepadSupport.IsActive) { return; } GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject; if ((Object)(object)currentSelectedGameObject == (Object)null || !currentSelectedGameObject.activeInHierarchy || !currentSelectedGameObject.transform.IsChildOf((Transform)(object)_scroll.content)) { return; } RectTransform val = (RectTransform)(((Object)(object)_scroll.viewport != (Object)null) ? ((object)_scroll.viewport) : ((object)(RectTransform)((Component)_scroll).transform)); Transform transform = currentSelectedGameObject.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 == (Object)null) { return; } Bounds val3 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)val, (Transform)(object)val2); Rect rect = val.rect; float num; if (((Bounds)(ref val3)).max.y + 12f > ((Rect)(ref rect)).yMax) { num = ((Bounds)(ref val3)).max.y + 12f - ((Rect)(ref rect)).yMax; } else { if (!(((Bounds)(ref val3)).min.y - 12f < ((Rect)(ref rect)).yMin)) { return; } num = ((Bounds)(ref val3)).min.y - 12f - ((Rect)(ref rect)).yMin; } RectTransform content = _scroll.content; Rect rect2 = content.rect; float num2 = Mathf.Max(0f, ((Rect)(ref rect2)).height - ((Rect)(ref rect)).height); Vector2 anchoredPosition = content.anchoredPosition; anchoredPosition.y = Mathf.Clamp(anchoredPosition.y - num, 0f, num2); content.anchoredPosition = anchoredPosition; _scroll.velocity = Vector2.zero; } } internal sealed class GamepadFocusKeeper : MonoBehaviour { private Transform _panelRoot; private Func<Selectable> _fallback; internal static void Attach(GameObject host, Transform panelRoot, Func<Selectable> fallback) { if (!((Object)(object)host == (Object)null)) { GamepadFocusKeeper obj = host.GetComponent<GamepadFocusKeeper>() ?? host.AddComponent<GamepadFocusKeeper>(); obj._panelRoot = panelRoot; obj._fallback = fallback; } } internal void FocusFallback() { GamepadSupport.Select(_fallback?.Invoke()); } private void Update() { if ((Object)(object)EventSystem.current == (Object)null || !GamepadSupport.IsActive || KeybindCapture.IsListening || KeybindCapture.CommittedThisFrame || ModPicker.IsAnyOpen || PresetEditDialog.IsOpen) { return; } GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject; if (!((Object)(object)currentSelectedGameObject != (Object)null) || !currentSelectedGameObject.activeInHierarchy || !((Object)(object)_panelRoot != (Object)null) || !currentSelectedGameObject.transform.IsChildOf(_panelRoot)) { FocusFallback(); } else if (GamepadSupport.GetButtonDown(GamepadSupport.RenameButton)) { RightClickRelay component = currentSelectedGameObject.GetComponent<RightClickRelay>(); if ((Object)(object)component != (Object)null) { component.Invoke(); } } } } internal sealed class ControllerGlyph : MonoBehaviour { private TMP_Text _text; private string _key; private string _shown; internal static ControllerGlyph Create(Transform parent, string key, TMP_Text fontSource) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if ((Object)(object)parent == (Object)null) { return null; } GameObject val = new GameObject("ControllerGlyph_" + key, new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); val.transform.SetParent(parent, false); LayoutElement component = val.GetComponent<LayoutElement>(); component.minWidth = 30f; component.preferredWidth = 30f; component.flexibleWidth = 0f; component.minHeight = 30f; TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).richText = true; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).fontSize = 22f; ((TMP_Text)val2).enableAutoSizing = false; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; if ((Object)(object)fontSource != (Object)null) { ((TMP_Text)val2).font = fontSource.font; ((TMP_Text)val2).fontSharedMaterial = fontSource.fontSharedMaterial; if ((Object)(object)fontSource.spriteAsset != (Object)null) { ((TMP_Text)val2).spriteAsset = fontSource.spriteAsset; } } ControllerGlyph controllerGlyph = val.AddComponent<ControllerGlyph>(); controllerGlyph._text = (TMP_Text)(object)val2; controllerGlyph._key = key; val.SetActive(false); return controllerGlyph; } internal static ControllerGlyph CreateCorner(Transform parent, string key, TMP_Text fontSource) { //IL_0025: 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_004f: 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_0078: Unknown result type (might be due to invalid IL or missing references) ControllerGlyph controllerGlyph = Create(parent, key, fontSource); if ((Object)(object)controllerGlyph == (Object)null) { return null; } RectTransform component = ((Component)controllerGlyph).GetComponent<RectTransform>(); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-1f, -1f); component.sizeDelta = new Vector2(22f, 22f); ((Component)controllerGlyph).GetComponent<LayoutElement>().ignoreLayout = true; controllerGlyph._text.fontSize = 18f; ((Component)controllerGlyph).transform.SetAsLastSibling(); return controllerGlyph; } internal void UseKey(string key) { if (!string.Equals(_key, key, StringComparison.Ordinal)) { _key = key; _shown = null; } } internal void SetVisible(bool visible) { string text = (visible ? Lookup(_key) : null); bool flag = !string.IsNullOrEmpty(text); if (flag && text != _shown) { _shown = text; _text.text = text; } if (((Component)this).gameObject.activeSelf != flag) { ((Component)this).gameObject.SetActive(flag); } } private static string Lookup(string key) { try { ZInput instance = ZInput.instance; if (instance == null) { return null; } string boundKeyString = instance.GetBoundKeyString(key, true); return (string.IsNullOrEmpty(boundKeyString) || boundKeyString.IndexOf('<') < 0) ? null : boundKeyString; } catch { return null; } } } internal sealed class SliderValueLink : MonoBehaviour, ISubmitHandler, IEventSystemHandler { private GuiInputField _value; internal static void Attach(Slider slider, GuiInputField value) { if (!((Object)(object)slider == (Object)null) && !((Object)(object)value == (Object)null)) { SliderValueLink sliderValueLink = ((Component)slider).GetComponent<SliderValueLink>(); if ((Object)(object)sliderValueLink == (Object)null) { sliderValueLink = ((Component)slider).gameObject.AddComponent<SliderValueLink>(); } sliderValueLink._value = value; SliderValueAnchor sliderValueAnchor = ((Component)value).GetComponent<SliderValueAnchor>(); if ((Object)(object)sliderValueAnchor == (Object)null) { sliderValueAnchor = ((Component)value).gameObject.AddComponent<SliderValueAnchor>(); } sliderValueAnchor.Slider = slider; } } internal static Slider SliderFor(GuiInputField field) { if (!((Object)(object)field != (Object)null)) { return null; } return ((Component)field).GetComponent<SliderValueAnchor>()?.Slider; } public void OnSubmit(BaseEventData eventData) { if (!((Object)(object)_value == (Object)null) && ((Behaviour)_value).isActiveAndEnabled && ((Selectable)_value).interactable && !((TMP_InputField)_value).readOnly && !KeybindCapture.IsListening && !KeybindCapture.CommittedThisFrame && !ModPicker.IsAnyOpen && !PresetEditDialog.IsOpen) { GamepadSupport.Select((Selectable)(object)_value); _value.ActivateInputField(); } } } internal sealed class SelectedRenameGlyph : MonoBehaviour { private ControllerGlyph _glyph; internal static void Attach(GameObject target, TMP_Text fontSource) { if (!((Object)(object)target == (Object)null)) { SelectedRenameGlyph selectedRenameGlyph = target.GetComponent<SelectedRenameGlyph>() ?? target.AddComponent<SelectedRenameGlyph>(); if ((Object)(object)selectedRenameGlyph._glyph == (Object)null) { selectedRenameGlyph._glyph = ControllerGlyph.CreateCorner(target.transform, GamepadSupport.RenameButton, fontSource); } } } private void LateUpdate() { if (!((Object)(object)_glyph == (Object)null)) { GameObject val = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null); _glyph.UseKey(GamepadSupport.RenameButton); _glyph.SetVisible(GamepadSupport.IsActive && (Object)(object)val == (Object)(object)((Component)this).gameObject); } } } internal sealed class SliderValueAnchor : MonoBehaviour { internal Slider Slider; } internal sealed class SliderStep : MonoBehaviour, IMoveHandler, IEventSystemHandler { private Slider _slider; internal static void Attach(Slider slider) { if (!((Object)(object)slider == (Object)null)) { SliderStep sliderStep = ((Component)slider).GetComponent<SliderStep>(); if ((Object)(object)sliderStep == (Object)null) { sliderStep = ((Component)slider).gameObject.AddComponent<SliderStep>(); } sliderStep._slider = slider; PointNavigationAtSelf(slider); } } public void OnMove(AxisEventData eventData) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 if (!((Object)(object)_slider == (Object)null) && ((UIBehaviour)_slider).IsActive() && ((Selectable)_slider).IsInteractable() && ((int)eventData.moveDir == 0 || (int)eventData.moveDir == 2)) { PointNavigationAtSelf(_slider); Step(((int)eventData.moveDir == 2) ? 1 : (-1)); } } private void Step(int direction) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((int)_slider.direction == 1 || (int)_slider.direction == 3) { direction = -direction; } float minValue = _slider.minValue; float maxValue = _slider.maxValue; float num = NiceStep(minValue, maxValue, _slider.wholeNumbers); if (!(num <= 0f)) { float num2 = _slider.value / num; float num3 = ((direction > 0) ? (Mathf.Floor(num2 + 0.0001f) + 1f) : (Mathf.Ceil(num2 - 0.0001f) - 1f)) * num; num3 = (_slider.wholeNumbers ? Mathf.Round(num3) : RoundToStep(num3, num)); num3 = Mathf.Clamp(num3, minValue, maxValue); if (!Mathf.Approximately(num3, _slider.value)) { _slider.value = num3; } } } private static void PointNavigationAtSelf(Slider slider) { //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) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) Navigation navigation = ((Selectable)slider).navigation; if ((int)((Navigation)(ref navigation)).mode != 4 || !((Object)(object)((Navigation)(ref navigation)).selectOnLeft == (Object)(object)s