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 Supermans Configs v1.1.0
SupermansConfigs.dll
Decompiled 2 weeks agousing System; 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.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ModMenu { internal class ConfigMenu : MonoBehaviour { private class ModInfo { public string Guid; public string Title; public string Version; public ConfigFile Config; public List<KeyValuePair<string, List<ConfigEntryBase>>> Sections; } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static class MouseCapturePatch { private static void Postfix() { if (IsOpen) { ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); } } } [HarmonyPatch(typeof(Player), "TakeInput")] private static class PlayerTakeInputPatch { private static void Postfix(ref bool __result) { if (IsOpen) { __result = false; } } } [HarmonyPatch] private static class ControllerTakeInputPatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(PlayerController), "TakeInput", (Type[])null, (Type[])null); } private static bool Prepare() { return (TargetMethod() as MethodInfo)?.ReturnType == typeof(bool); } private static void Postfix(ref bool __result) { if (IsOpen) { __result = false; } } } [HarmonyPatch(typeof(Menu), "Update")] private static class MenuPatch { private static bool Prefix() { return !BlockGameMenu; } } private const int WindowId = 1397574990; private static readonly KeyCode[] Modifiers; private static ConfigEntryBase _capturing; private static bool _refreshRequested; private static int _suppressFrame; private static KeyCode[] _bindableKeys; private List<ModInfo> _mods = new List<ModInfo>(); private int _selected; private int _pendingSelect = -1; private bool _showUpdates; private string _searchInput = ""; private string _search = ""; private Vector2 _listScroll; private Vector2 _entryScroll; private Rect _rect = new Rect(0f, 0f, 860f, 640f); private bool _centered; private string _tooltip = ""; private float _confirmResetUntil; private readonly Dictionary<ConfigEntryBase, string> _textBuffers = new Dictionary<ConfigEntryBase, string>(); private GUIStyle _window; private GUIStyle _header; private GUIStyle _modHeader; private GUIStyle _label; private GUIStyle _wrap; private GUIStyle _tip; private GUIStyle _toast; private GUIStyle _modButton; private GUIStyle _modButtonSelected; internal static bool IsOpen { get; private set; } internal static bool IsCapturingKey { get { if (_capturing == null) { return Time.frameCount <= _suppressFrame; } return true; } } internal static bool BlockGameMenu { get { if (!IsOpen) { return Time.frameCount <= _suppressFrame; } return true; } } internal static void Toggle() { if (IsOpen) { Close(); return; } IsOpen = true; _refreshRequested = true; UpdateChecker.RequestScan(); } private static void Close() { IsOpen = false; _capturing = null; _suppressFrame = Time.frameCount; } private void Update() { if (IsOpen && ZInput.instance != null) { if (_capturing != null) { UpdateKeyCapture(); } else if (ZInput.GetKeyDown((KeyCode)27, false)) { Close(); SaveUnsaved(); } } } private void OnGUI() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { DrawToast(); return; } if ((int)Event.current.type == 8) { if (_mods.Count == 0 || _pendingSelect == -2 || _refreshRequested) { RefreshMods(); } _refreshRequested = false; if (_pendingSelect >= 0) { _selected = _pendingSelect; _showUpdates = false; _entryScroll = Vector2.zero; } if (_pendingSelect == -3) { _showUpdates = true; _entryScroll = Vector2.zero; } _pendingSelect = -1; _search = _searchInput.Trim(); } BuildStyles(); float value = Plugin.UiScale.Value; GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(value, value, 1f)); float num = (float)Screen.width / value; float num2 = (float)Screen.height / value; ((Rect)(ref _rect)).width = Mathf.Min(860f, num - 20f); ((Rect)(ref _rect)).height = Mathf.Min(640f, num2 - 20f); if (!_centered) { ((Rect)(ref _rect)).x = (num - ((Rect)(ref _rect)).width) / 2f; ((Rect)(ref _rect)).y = (num2 - ((Rect)(ref _rect)).height) / 2f; _centered = true; } _rect = GUILayout.Window(1397574990, _rect, new WindowFunction(DrawWindow), $"Supermans Configs ({Plugin.MenuKey.Value} to close)", _window, Array.Empty<GUILayoutOption>()); ((Rect)(ref _rect)).x = Mathf.Clamp(((Rect)(ref _rect)).x, 0f, num - ((Rect)(ref _rect)).width); ((Rect)(ref _rect)).y = Mathf.Clamp(((Rect)(ref _rect)).y, 0f, num2 - ((Rect)(ref _rect)).height); } private void DrawWindow(int id) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Invalid comparison between Unknown and I4 //IL_0479: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(210f) }); GUILayout.Label("Search all mods", _label, Array.Empty<GUILayoutOption>()); _searchInput = GUILayout.TextField(_searchInput, Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); int count = UpdateChecker.Findings.Count; if (GUILayout.Button((count > 0) ? $"<b><color=#7ad1ff>Updates ({count})</color></b>" : "Updates <size=11><color=#a89a86>(up to date)</color></size>", (_showUpdates && _search.Length == 0) ? _modButtonSelected : _modButton, Array.Empty<GUILayoutOption>())) { _pendingSelect = -3; _searchInput = ""; } GUILayout.Space(4f); _listScroll = GUILayout.BeginScrollView(_listScroll, Array.Empty<GUILayoutOption>()); for (int i = 0; i < _mods.Count; i++) { GUIStyle val = ((i == _selected && !_showUpdates && _search.Length == 0) ? _modButtonSelected : _modButton); UpdateChecker.Finding finding = UpdateChecker.For(_mods[i].Guid); string text = ((finding == null) ? "" : (finding.NeedsRestart ? " <color=#7ad1ff>restart</color>" : " <color=#7ad1ff>update</color>")); if (GUILayout.Button(_mods[i].Title + "\n<size=11><color=#a89a86>v" + _mods[i].Version + "</color>" + text + "</size>", val, Array.Empty<GUILayoutOption>())) { _pendingSelect = i; _searchInput = ""; } } if (_mods.Count == 0) { GUILayout.Label("No Supermans mods found.", _label, Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); if (GUILayout.Button("Refresh list", Array.Empty<GUILayoutOption>())) { _pendingSelect = -2; } GUILayout.EndVertical(); GUILayout.Space(8f); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); _entryScroll = GUILayout.BeginScrollView(_entryScroll, Array.Empty<GUILayoutOption>()); if (_search.Length > 0) { DrawSearchResults(); } else if (_showUpdates) { DrawUpdates(); } else if (_selected < _mods.Count) { DrawMod(_mods[_selected]); } GUILayout.EndScrollView(); GUILayout.Label(_tooltip, _tip, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(44f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (_search.Length == 0 && !_showUpdates && _selected < _mods.Count) { ModInfo modInfo = _mods[_selected]; bool flag = Time.realtimeSinceStartup < _confirmResetUntil; if (GUILayout.Button(flag ? ("Click again to reset " + modInfo.Title) : "Reset this mod to defaults", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(280f) })) { if (flag) { foreach (KeyValuePair<string, List<ConfigEntryBase>> section in modInfo.Sections) { foreach (ConfigEntryBase item in section.Value) { item.BoxedValue = item.DefaultValue; } } _textBuffers.Clear(); _confirmResetUntil = 0f; } else { _confirmResetUntil = Time.realtimeSinceStartup + 3f; } } GUILayout.Label("<size=11><color=#a89a86>Saved to BepInEx/config/" + modInfo.Guid + ".cfg</color></size>", _label, Array.Empty<GUILayoutOption>()); } GUILayout.FlexibleSpace(); if (GUILayout.Button("Close", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Close(); SaveUnsaved(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); if ((int)Event.current.type == 7) { _tooltip = GUI.tooltip; } GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); } private void DrawMod(ModInfo mod) { GUILayout.Label(mod.Title, _modHeader, Array.Empty<GUILayoutOption>()); foreach (KeyValuePair<string, List<ConfigEntryBase>> section in mod.Sections) { GUILayout.Label(PrettySection(section.Key), _header, Array.Empty<GUILayoutOption>()); foreach (ConfigEntryBase item in section.Value) { DrawEntry(item); } GUILayout.Space(6f); } } private void DrawUpdates() { GUILayout.Label("Updates", _modHeader, Array.Empty<GUILayoutOption>()); if (UpdateChecker.Findings.Count == 0) { GUILayout.Label("All your Supermans mods are up to date.", _label, Array.Empty<GUILayoutOption>()); } foreach (UpdateChecker.Finding finding in UpdateChecker.Findings) { GUILayout.Label(finding.Title, _header, Array.Empty<GUILayoutOption>()); GUILayout.Label(finding.Message, _wrap, Array.Empty<GUILayoutOption>()); GUILayout.Space(4f); } GUILayout.Space(10f); GUILayout.Label("<size=11><color=#a89a86>Checks your Gale profile and " + (string.IsNullOrWhiteSpace(Plugin.ModsFolder.Value) ? "no mods folder" : Plugin.ModsFolder.Value) + $" every {Plugin.CheckMinutes.Value:0} min. New Supermans mods are added to this menu automatically once Valheim loads them.</color></size>", _wrap, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Check now", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) })) { UpdateChecker.RequestScan(); } } private void DrawToast() { //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) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(UpdateChecker.ToastText) && !(Time.realtimeSinceStartup > UpdateChecker.ToastUntil)) { BuildStyles(); float value = Plugin.UiScale.Value; GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(value, value, 1f)); float num = 520f; GUI.Box(new Rect(((float)Screen.width / value - num) / 2f, 40f, num, 34f), UpdateChecker.ToastText, _toast); } } private void DrawSearchResults() { bool flag = false; foreach (ModInfo mod in _mods) { List<ConfigEntryBase> list = mod.Sections.SelectMany((KeyValuePair<string, List<ConfigEntryBase>> s) => s.Value).Where(Matches).ToList(); if (list.Count == 0) { continue; } flag = true; GUILayout.Label(mod.Title, _modHeader, Array.Empty<GUILayoutOption>()); foreach (ConfigEntryBase item in list) { DrawEntry(item); } GUILayout.Space(6f); } if (!flag) { GUILayout.Label("Nothing matches \"" + _search + "\".", _label, Array.Empty<GUILayoutOption>()); } } private bool Matches(ConfigEntryBase entry) { if (!Contains(entry.Definition.Key) && !Contains(PrettyKey(entry.Definition.Key)) && !Contains(entry.Definition.Section)) { ConfigDescription description = entry.Description; return Contains((description != null) ? description.Description : null); } return true; } private bool Contains(string text) { if (text != null) { return text.IndexOf(_search, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private void DrawEntry(ConfigEntryBase entry) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown Type settingType = entry.SettingType; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = PrettyKey(entry.Definition.Key); ConfigDescription description = entry.Description; GUILayout.Label(new GUIContent(text, ((description != null) ? description.Description : null) ?? ""), _label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) }); Array acceptableList = GetAcceptableList(entry); if (settingType == typeof(bool)) { DrawBool(entry); } else if (settingType == typeof(KeyCode) || settingType == typeof(KeyboardShortcut)) { DrawKey(entry); } else if (acceptableList != null) { DrawCycle(entry, acceptableList); } else if (settingType.IsEnum && !settingType.IsDefined(typeof(FlagsAttribute), inherit: false)) { DrawCycle(entry, Enum.GetValues(settingType)); } else if (IsNumeric(settingType)) { DrawNumber(entry); } else if (settingType == typeof(string)) { DrawString(entry); } else { DrawGeneric(entry); } bool enabled = GUI.enabled; GUI.enabled = !object.Equals(entry.BoxedValue, entry.DefaultValue); if (GUILayout.Button(new GUIContent("Reset", "Default: " + entry.DefaultValue), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(52f) })) { entry.BoxedValue = entry.DefaultValue; _textBuffers.Remove(entry); } GUI.enabled = enabled; GUILayout.EndHorizontal(); } private static void DrawBool(ConfigEntryBase entry) { bool flag = (bool)entry.BoxedValue; bool flag2 = GUILayout.Toggle(flag, flag ? " On" : " Off", Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (flag2 != flag) { entry.BoxedValue = flag2; } } private static void DrawCycle(ConfigEntryBase entry, Array values) { int num = Array.IndexOf(values, entry.BoxedValue); if (GUILayout.Button("<", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }) && values.Length > 0) { entry.BoxedValue = values.GetValue((num <= 0) ? (values.Length - 1) : (num - 1)); } GUILayout.Box(entry.BoxedValue?.ToString() ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button(">", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }) && values.Length > 0) { entry.BoxedValue = values.GetValue((num + 1) % values.Length); } } private void DrawKey(ConfigEntryBase entry) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (GUILayout.Button((_capturing == entry) ? "<color=#ffd27a>Press a key... (Esc cancels)</color>" : entry.BoxedValue.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) })) { _capturing = entry; GUIUtility.keyboardControl = 0; } if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(52f) })) { entry.BoxedValue = ((entry.SettingType == typeof(KeyCode)) ? ((object)(KeyCode)0) : ((object)KeyboardShortcut.Empty)); _capturing = null; } } private void DrawNumber(ConfigEntryBase entry) { Type settingType = entry.SettingType; bool flag = settingType != typeof(float) && settingType != typeof(double) && settingType != typeof(decimal); double num = Convert.ToDouble(entry.BoxedValue, CultureInfo.InvariantCulture); if (TryGetRange(entry, out var min, out var max)) { float num2 = GUILayout.HorizontalSlider((float)num, (float)min, (float)max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (!Mathf.Approximately(num2, (float)num)) { double value = (flag ? Math.Round(num2) : Math.Round(num2, Decimals(max - min))); SetNumber(entry, value); _textBuffers.Remove(entry); } } else { GUILayout.FlexibleSpace(); } string text = "num" + ((object)entry).GetHashCode(); if (GUI.GetNameOfFocusedControl() != text || !_textBuffers.ContainsKey(entry)) { _textBuffers[entry] = FormatNumber(entry.BoxedValue); } GUI.SetNextControlName(text); string text2 = GUILayout.TextField(_textBuffers[entry], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); if (text2 != _textBuffers[entry]) { _textBuffers[entry] = text2; if (double.TryParse(text2.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { SetNumber(entry, result); } } } private static void DrawString(ConfigEntryBase entry) { string text = ((string)entry.BoxedValue) ?? ""; string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (text2 != text) { entry.BoxedValue = text2; } } private void DrawGeneric(ConfigEntryBase entry) { string text = "gen" + ((object)entry).GetHashCode(); if (GUI.GetNameOfFocusedControl() != text || !_textBuffers.ContainsKey(entry)) { _textBuffers[entry] = entry.GetSerializedValue(); } GUI.SetNextControlName(text); string text2 = GUILayout.TextField(_textBuffers[entry], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (text2 == _textBuffers[entry]) { return; } _textBuffers[entry] = text2; try { if (TomlTypeConverter.CanConvert(entry.SettingType)) { entry.BoxedValue = TomlTypeConverter.ConvertToValue(text2, entry.SettingType); } } catch { } } private static void UpdateKeyCapture() { //IL_0093: 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) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if (_bindableKeys == null) { _bindableKeys = (from KeyCode k in Enum.GetValues(typeof(KeyCode)) where (int)k != 0 && (int)k != 323 && (int)k != 324 && (int)k < 330 select k).Distinct().ToArray(); } if (ZInput.GetKeyDown((KeyCode)27, false)) { _capturing = null; _suppressFrame = Time.frameCount; return; } bool flag = _capturing.SettingType == typeof(KeyboardShortcut); KeyCode[] bindableKeys = _bindableKeys; foreach (KeyCode val in bindableKeys) { if (!ZInput.GetKeyDown(val, false) || (flag && Modifiers.Contains(val))) { continue; } if (flag) { KeyCode[] array = Modifiers.Where((KeyCode m) => ZInput.GetKey(m, false)).ToArray(); _capturing.BoxedValue = (object)new KeyboardShortcut(val, array); } else { _capturing.BoxedValue = val; } _capturing = null; _suppressFrame = Time.frameCount; break; } } private void RefreshMods() { string selectedGuid = ((_selected < _mods.Count) ? _mods[_selected].Guid : null); _mods = new List<ModInfo>(); _textBuffers.Clear(); foreach (PluginInfo value in Chainloader.PluginInfos.Values) { if ((Object)(object)((value != null) ? value.Instance : null) == (Object)null || !Plugin.IsSupermanMod(value)) { continue; } string gUID = value.Metadata.GUID; string input = value.Metadata.Name ?? gUID; List<KeyValuePair<string, List<ConfigEntryBase>>> list = new List<KeyValuePair<string, List<ConfigEntryBase>>>(); foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> pair in value.Instance.Config) { if (IsBrowsable(pair.Value)) { List<ConfigEntryBase> list2 = list.FirstOrDefault((KeyValuePair<string, List<ConfigEntryBase>> s) => s.Key == pair.Key.Section).Value; if (list2 == null) { list2 = new List<ConfigEntryBase>(); list.Add(new KeyValuePair<string, List<ConfigEntryBase>>(pair.Key.Section, list2)); } list2.Add(pair.Value); } } if (list.Count != 0) { list.Sort((KeyValuePair<string, List<ConfigEntryBase>> a, KeyValuePair<string, List<ConfigEntryBase>> b) => string.CompareOrdinal(a.Key, b.Key)); _mods.Add(new ModInfo { Guid = gUID, Title = Regex.Replace(input, "^Supermans?\\s*", "", RegexOptions.IgnoreCase), Version = value.Metadata.Version.ToString(), Config = value.Instance.Config, Sections = list }); } } _mods = _mods.OrderBy((ModInfo m) => m.Guid == "supermans.configs").ThenBy<ModInfo, string>((ModInfo m) => m.Title, StringComparer.OrdinalIgnoreCase).ToList(); _selected = Math.Max(0, _mods.FindIndex((ModInfo m) => m.Guid == selectedGuid)); } private static bool IsBrowsable(ConfigEntryBase entry) { ConfigDescription description = entry.Description; object[] array = ((description != null) ? description.Tags : null); if (array == null) { return true; } object[] array2 = array; foreach (object obj in array2) { if (obj != null && !(obj.GetType().Name != "ConfigurationManagerAttributes")) { object obj2 = obj.GetType().GetField("Browsable")?.GetValue(obj); if (obj2 is bool && !(bool)obj2) { return false; } } } return true; } private void SaveUnsaved() { foreach (ModInfo mod in _mods) { if (!mod.Config.SaveOnConfigSet) { mod.Config.Save(); } } } private static bool IsNumeric(Type t) { if (!(t == typeof(int)) && !(t == typeof(float)) && !(t == typeof(double)) && !(t == typeof(long)) && !(t == typeof(short)) && !(t == typeof(byte)) && !(t == typeof(uint)) && !(t == typeof(ulong)) && !(t == typeof(ushort)) && !(t == typeof(sbyte))) { return t == typeof(decimal); } return true; } private static void SetNumber(ConfigEntryBase entry, double value) { try { entry.BoxedValue = Convert.ChangeType(value, entry.SettingType, CultureInfo.InvariantCulture); } catch (OverflowException) { } } private static string FormatNumber(object value) { if (value is float num) { return num.ToString("0.###", CultureInfo.InvariantCulture); } if (value is double num2) { return num2.ToString("0.###", CultureInfo.InvariantCulture); } return Convert.ToString(value, CultureInfo.InvariantCulture); } private static int Decimals(double span) { double num = span / 200.0; if (num <= 0.0) { return 2; } return Mathf.Clamp(Mathf.CeilToInt(0f - (float)Math.Log10(num)), 0, 4); } private static bool TryGetRange(ConfigEntryBase entry, out double min, out double max) { min = (max = 0.0); ConfigDescription description = entry.Description; object obj = ((description != null) ? description.AcceptableValues : null); if (obj == null || !obj.GetType().IsGenericType || obj.GetType().GetGenericTypeDefinition() != typeof(AcceptableValueRange<>)) { return false; } min = Convert.ToDouble(obj.GetType().GetProperty("MinValue").GetValue(obj, null), CultureInfo.InvariantCulture); max = Convert.ToDouble(obj.GetType().GetProperty("MaxValue").GetValue(obj, null), CultureInfo.InvariantCulture); return max > min; } private static Array GetAcceptableList(ConfigEntryBase entry) { ConfigDescription description = entry.Description; object obj = ((description != null) ? description.AcceptableValues : null); if (obj == null || !obj.GetType().IsGenericType || obj.GetType().GetGenericTypeDefinition() != typeof(AcceptableValueList<>)) { return null; } return obj.GetType().GetProperty("AcceptableValues", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj, null) as Array; } private static string PrettySection(string section) { return Regex.Replace(section, "^\\s*\\d+\\s*-\\s*", ""); } private static string PrettyKey(string key) { return Regex.Replace(key, "(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])", " "); } private void BuildStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0040: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Expected O, but got Unknown //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_0277: Expected O, but got Unknown //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Expected O, but got Unknown //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) if (_window == null) { _window = new GUIStyle(GUI.skin.window) { richText = true, fontSize = 15, padding = new RectOffset(12, 12, 28, 10) }; Texture2D background = SolidTexture(new Color(0.11f, 0.09f, 0.07f, 0.97f)); _window.normal.background = background; _window.onNormal.background = background; GUIStyleState normal = _window.normal; GUIStyleState onNormal = _window.onNormal; Color textColor = default(Color); ((Color)(ref textColor))..ctor(1f, 0.82f, 0.48f); onNormal.textColor = textColor; normal.textColor = textColor; _label = new GUIStyle(GUI.skin.label) { richText = true, wordWrap = false }; _wrap = new GUIStyle(_label) { wordWrap = true }; _toast = new GUIStyle(GUI.skin.box) { richText = true, alignment = (TextAnchor)4, fontSize = 14 }; _toast.normal.background = SolidTexture(new Color(0.11f, 0.09f, 0.07f, 0.92f)); _toast.normal.textColor = new Color(1f, 0.82f, 0.48f); _header = new GUIStyle(GUI.skin.label) { richText = true, fontStyle = (FontStyle)1, fontSize = 14 }; _header.normal.textColor = new Color(1f, 0.82f, 0.48f); _modHeader = new GUIStyle(_header) { fontSize = 18 }; _modHeader.normal.textColor = Color.white; _tip = new GUIStyle(GUI.skin.box) { wordWrap = true, richText = true, alignment = (TextAnchor)0, fontSize = 12 }; _tip.normal.textColor = new Color(0.85f, 0.8f, 0.72f); _modButton = new GUIStyle(GUI.skin.button) { richText = true, alignment = (TextAnchor)3, padding = new RectOffset(10, 6, 6, 6) }; _modButtonSelected = new GUIStyle(_modButton); Texture2D background2 = SolidTexture(new Color(0.55f, 0.38f, 0.12f, 1f)); _modButtonSelected.normal.background = background2; _modButtonSelected.hover.background = background2; textColor = (_modButtonSelected.normal.textColor = (_modButtonSelected.hover.textColor = Color.white)); } } private static Texture2D SolidTexture(Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1) { hideFlags = (HideFlags)61 }; val.SetPixel(0, 0, color); val.Apply(); return val; } static ConfigMenu() { KeyCode[] array = new KeyCode[6]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Modifiers = (KeyCode[])(object)array; _suppressFrame = -1; } } [BepInPlugin("supermans.configs", "Supermans Configs", "1.1.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "supermans.configs"; public const string Name = "Supermans Configs"; public const string Version = "1.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<KeyCode> MenuKey; internal static ConfigEntry<float> UiScale; internal static ConfigEntry<string> ExtraMods; internal static ConfigEntry<bool> UpdateNotifications; internal static ConfigEntry<float> CheckMinutes; internal static ConfigEntry<string> ModsFolder; private Harmony _harmony; private void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1 - General", "MenuKey", (KeyCode)283, "Opens/closes the Supermans Configs menu."); UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "UiScale", 1f, new ConfigDescription("Size of the settings menu.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.75f, 2f), Array.Empty<object>())); ExtraMods = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "ExtraMods", "chestlink.valheim", "Comma-separated plugin GUIDs to list in the menu besides mods whose name or GUID contains \"superman\"."); UpdateNotifications = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Updates", "Notifications", true, "Show a notice on screen when a Supermans mod is added or updated."); CheckMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Updates", "CheckMinutes", 5f, new ConfigDescription("How often (minutes) to look for added or updated Supermans mods.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>())); ModsFolder = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Updates", "ModsFolder", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "My Designed Mods for Valheim"), "Folder holding your packaged Supermans_*-<version>.zip files. A newer zip here than what is installed shows as an update. Leave empty to skip."); ((Component)this).gameObject.AddComponent<ConfigMenu>(); _harmony = new Harmony("supermans.configs"); _harmony.PatchAll(); Log.LogInfo((object)"Supermans Configs 1.1.0 loaded"); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) UpdateChecker.Tick(); if (ZInput.instance != null && !ConfigMenu.IsCapturingKey && ZInput.GetKeyDown(MenuKey.Value, false) && !IsTyping()) { ConfigMenu.Toggle(); } } internal static bool IsSupermanMod(PluginInfo info) { string guid = info.Metadata.GUID; string text = info.Metadata.Name ?? guid; if (guid.IndexOf("superman", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("superman", StringComparison.OrdinalIgnoreCase) < 0) { return (ExtraMods.Value ?? "").Split(new char[1] { ',' }).Any((string s) => string.Equals(s.Trim(), guid, StringComparison.OrdinalIgnoreCase)); } return true; } private static bool IsTyping() { if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible()) { return TextInput.IsVisible(); } return true; } } internal static class UpdateChecker { internal class Finding { public string Package; public string Title; public string PluginGuid; public string Message; public bool NeedsRestart; } private class Package { public string Name; public Version Version; public string Dir; public PluginInfo Loaded; } private static readonly HashSet<string> Notified = new HashSet<string>(); private static float _nextScan = 5f; internal static List<Finding> Findings { get; private set; } = new List<Finding>(); internal static string ToastText { get; private set; } internal static float ToastUntil { get; private set; } internal static void RequestScan() { _nextScan = 0f; } internal static void Tick() { if (Time.realtimeSinceStartup < _nextScan) { return; } _nextScan = Time.realtimeSinceStartup + Mathf.Max(1f, Plugin.CheckMinutes.Value) * 60f; try { Scan(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Update check failed: " + ex.Message)); } } internal static Finding For(string pluginGuid) { return Findings.FirstOrDefault((Finding f) => f.PluginGuid == pluginGuid); } private static void Scan() { //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Package> dictionary = ScanInstalled(); Dictionary<string, Version> dictionary2 = ScanModsFolder(); List<Finding> list = new List<Finding>(); foreach (Package value2 in dictionary.Values) { if (value2.Loaded == null) { list.Add(new Finding { Package = value2.Name, Title = Pretty(value2.Name), NeedsRestart = true, Message = $"v{value2.Version} was added to your Gale profile. Restart Valheim to load it." }); } else if (value2.Version != null && value2.Version > value2.Loaded.Metadata.Version) { list.Add(new Finding { Package = value2.Name, Title = Pretty(value2.Name), PluginGuid = value2.Loaded.Metadata.GUID, NeedsRestart = true, Message = $"Updated to v{value2.Version} (running v{value2.Loaded.Metadata.Version}). Restart Valheim to apply." }); } } foreach (KeyValuePair<string, Version> item in dictionary2) { dictionary.TryGetValue(Normalize(item.Key), out var value); if (value == null || !(value.Version != null) || !(value.Version >= item.Value)) { Finding obj = new Finding { Package = item.Key, Title = Pretty(item.Key) }; object pluginGuid; if (value == null) { pluginGuid = null; } else { PluginInfo loaded = value.Loaded; pluginGuid = ((loaded != null) ? loaded.Metadata.GUID : null); } obj.PluginGuid = (string)pluginGuid; obj.Message = ((value == null) ? $"New mod v{item.Value} is in your mods folder. Import it in Gale (Import > local mod)." : $"v{item.Value} is in your mods folder (installed v{value.Version}). Import it in Gale (Import > local mod)."); list.Add(obj); } } Findings = list.OrderBy<Finding, string>((Finding f) => f.Title, StringComparer.OrdinalIgnoreCase).ToList(); int num = Findings.Count((Finding f) => Notified.Add(f.Package + "|" + f.Message)); if (num > 0 && Plugin.UpdateNotifications.Value) { ToastText = ((num == 1) ? $"Supermans Configs: {Findings.First().Title} has an update. Press {Plugin.MenuKey.Value} for details." : $"Supermans Configs: {num} mod updates found. Press {Plugin.MenuKey.Value} for details."); ToastUntil = Time.realtimeSinceStartup + 12f; } } private static Dictionary<string, Package> ScanInstalled() { Dictionary<string, Package> dictionary = new Dictionary<string, Package>(); if (!Directory.Exists(Paths.PluginPath)) { return dictionary; } string[] files = Directory.GetFiles(Paths.PluginPath, "manifest.json", SearchOption.AllDirectories); foreach (string path in files) { string json = File.ReadAllText(path); string text = JsonString(json, "name"); if (text != null && IsSuperman(text)) { string directoryName = Path.GetDirectoryName(path); if (Directory.GetFiles(directoryName, "*", SearchOption.AllDirectories).Any((string f) => f.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))) { dictionary[Normalize(text)] = new Package { Name = text, Version = ParseVersion(JsonString(json, "version_number")), Dir = directoryName }; } } } foreach (PluginInfo value in Chainloader.PluginInfos.Values) { if (value != null && value.Location != null && Plugin.IsSupermanMod(value)) { string pluginDir = Path.GetFullPath(Path.GetDirectoryName(value.Location)); Package package = dictionary.Values.FirstOrDefault((Package p) => pluginDir.StartsWith(Path.GetFullPath(p.Dir), StringComparison.OrdinalIgnoreCase)); if (package != null) { package.Loaded = value; } } } return dictionary; } private static Dictionary<string, Version> ScanModsFolder() { Dictionary<string, Version> dictionary = new Dictionary<string, Version>(StringComparer.OrdinalIgnoreCase); string value = Plugin.ModsFolder.Value; if (string.IsNullOrWhiteSpace(value) || !Directory.Exists(value)) { return dictionary; } string[] files = Directory.GetFiles(value, "*.zip"); for (int i = 0; i < files.Length; i++) { Match match = Regex.Match(Path.GetFileNameWithoutExtension(files[i]), "^(?<name>.+?)-(?<ver>\\d+(?:\\.\\d+){1,3})$"); if (match.Success && IsSuperman(match.Groups["name"].Value)) { Version version = ParseVersion(match.Groups["ver"].Value); string value2 = match.Groups["name"].Value; if (version != null && (!dictionary.TryGetValue(value2, out var value3) || version > value3)) { dictionary[value2] = version; } } } return dictionary; } private static bool IsSuperman(string name) { return name.IndexOf("superman", StringComparison.OrdinalIgnoreCase) >= 0; } private static string Normalize(string name) { return Regex.Replace(name, "[^a-zA-Z0-9]", "").ToLowerInvariant(); } private static string Pretty(string package) { return Regex.Replace(package, "^Supermans?[_ ]*", "", RegexOptions.IgnoreCase).Replace('_', ' '); } private static string JsonString(string json, string key) { Match match = Regex.Match(json, "\"" + key + "\"\\s*:\\s*\"([^\"]*)\""); if (!match.Success) { return null; } return match.Groups[1].Value; } private static Version ParseVersion(string text) { try { return string.IsNullOrEmpty(text) ? null : new Version(text); } catch { return null; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }