using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Ox1;
using Trash;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UIElements;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ModSettings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+a507aeb1f3310ba08f9aabd708fe2f1dc170f347")]
[assembly: AssemblyProduct("ModSettings")]
[assembly: AssemblyTitle("ModSettings")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ModSettings
{
internal sealed class ConfigurationManagerAttributes
{
public string DispName;
public int? Order;
}
internal static class ConfigWriter
{
private static readonly HashSet<ConfigFile> Dirty = new HashSet<ConfigFile>();
private static readonly HashSet<string> LoggedSaveFailures = new HashSet<string>();
private static readonly SaveSchedule Schedule = new SaveSchedule();
public static bool Set(ConfigEntryBase entry, object value)
{
ConfigFile configFile = entry.ConfigFile;
bool saveOnConfigSet = configFile.SaveOnConfigSet;
try
{
configFile.SaveOnConfigSet = false;
entry.BoxedValue = value;
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Couldn't set {entry.Definition} to '{value}': {arg}");
return false;
}
finally
{
configFile.SaveOnConfigSet = saveOnConfigSet;
}
if (saveOnConfigSet)
{
Dirty.Add(configFile);
Schedule.MarkDirty(Time.unscaledTime);
}
return true;
}
public static void Tick(float now)
{
if (Schedule.ShouldSave(now))
{
Save(now);
}
}
public static void Flush()
{
Save(Time.unscaledTime);
}
private static void Save(float now)
{
Schedule.Saved();
List<ConfigFile> list = new List<ConfigFile>();
foreach (ConfigFile item in Dirty)
{
try
{
item.Save();
LoggedSaveFailures.Remove(item.ConfigFilePath);
}
catch (Exception arg)
{
list.Add(item);
if (LoggedSaveFailures.Add(item.ConfigFilePath))
{
Plugin.Log.LogError((object)$"Couldn't save {item.ConfigFilePath}; retrying. {arg}");
}
}
}
Dirty.Clear();
foreach (ConfigFile item2 in list)
{
Dirty.Add(item2);
Schedule.MarkDirty(now);
}
}
}
internal enum EditorKind
{
Toggle,
Cycle,
Dropdown,
SliderInt,
Slider,
NumberText,
Text,
Key,
ReadOnly
}
internal enum Acceptable
{
None,
List,
Range
}
internal static class EditorKinds
{
public const int MaxCycleChoices = 6;
private static readonly Type[] Integers = new Type[8]
{
typeof(int),
typeof(long),
typeof(short),
typeof(byte),
typeof(sbyte),
typeof(uint),
typeof(ushort),
typeof(ulong)
};
private static readonly Type[] Reals = new Type[3]
{
typeof(float),
typeof(double),
typeof(decimal)
};
public static bool IsInteger(Type type)
{
return Array.IndexOf(Integers, type) >= 0;
}
public static bool IsReal(Type type)
{
return Array.IndexOf(Reals, type) >= 0;
}
public static EditorKind Choose(Type type, bool isShortcut, Acceptable acceptable, int listCount)
{
if (type == typeof(bool))
{
return EditorKind.Toggle;
}
if (isShortcut)
{
return EditorKind.Key;
}
if (acceptable == Acceptable.List)
{
if (listCount <= 6)
{
return EditorKind.Cycle;
}
return EditorKind.Dropdown;
}
if (type.IsEnum)
{
if (type.IsDefined(typeof(FlagsAttribute), inherit: false))
{
return EditorKind.ReadOnly;
}
if (Enum.GetValues(type).Length <= 6)
{
return EditorKind.Cycle;
}
return EditorKind.Dropdown;
}
if (acceptable == Acceptable.Range)
{
if (IsInteger(type))
{
return EditorKind.SliderInt;
}
if (IsReal(type))
{
return EditorKind.Slider;
}
}
if (IsInteger(type) || IsReal(type))
{
return EditorKind.NumberText;
}
if (type == typeof(string))
{
return EditorKind.Text;
}
return EditorKind.ReadOnly;
}
}
internal static class Hotkey
{
public static bool WasPressed(KeyboardShortcut shortcut)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
Keyboard current = Keyboard.current;
if (current == null || (int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
{
return false;
}
if (!TryGetKey(((KeyboardShortcut)(ref shortcut)).MainKey, out var key) || !((ButtonControl)current[key]).wasPressedThisFrame)
{
return false;
}
foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
{
if (!TryGetKey(modifier, out var key2) || !((ButtonControl)current[key2]).isPressed)
{
return false;
}
}
return true;
}
public unsafe static bool TryGetKey(KeyCode code, out Key key)
{
if (Enum.TryParse<Key>(KeyNames.ToKeyName(((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString()), ignoreCase: true, out key))
{
return (int)key != 0;
}
return false;
}
public unsafe static bool TryGetKeyCode(Key key, out KeyCode code)
{
if (Enum.TryParse<KeyCode>(KeyNames.ToKeyCodeName(((object)(*(Key*)(&key))/*cast due to .constrained prefix*/).ToString()), ignoreCase: true, out code))
{
return (int)code != 0;
}
return false;
}
}
internal sealed class HotkeyController : MonoBehaviour
{
private static readonly FieldInfo OpenStacks = typeof(MenuSceneManager).GetField("_stack", BindingFlags.Static | BindingFlags.NonPublic);
private static MenuScene _focusSwapped;
private static string _originalFocusName;
private bool _loggedError;
private void Update()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
try
{
KeyRebind.Tick();
ConfigWriter.Tick(Time.unscaledTime);
if (Hotkey.WasPressed(Plugin.OpenKey.Value))
{
OnOpenKey();
}
}
catch (Exception arg)
{
if (!_loggedError)
{
_loggedError = true;
Plugin.Log.LogError((object)$"Mod settings update failed. {arg}");
}
}
}
private void OnDestroy()
{
ConfigWriter.Flush();
RestoreFocusName();
}
private static void OnOpenKey()
{
FindHost(out var stack, out var hostScene, out var optionsScene);
OptionsUI active = ModsTabInstaller.Active;
switch (HotkeyGate.Decide(new HotkeyState
{
OptionsActive = ((Object)(object)active != (Object)null && ((Behaviour)active).isActiveAndEnabled),
TextFieldFocused = TextFieldFocused(active),
Rebinding = KeyRebind.Listening,
Loading = LoadingScreenUI.IsVisible,
MenusSuppressed = MenuSceneManager.MenusSuppressed,
HasMenuHost = ((Object)(object)stack != (Object)null && (Object)(object)optionsScene != (Object)null),
OtherMenuOpen = OtherMenuOpen(stack, hostScene, optionsScene)
}))
{
case HotkeyAction.ShowModsTab:
ModsTabInstaller.ShowMods(active);
break;
case HotkeyAction.OpenOptions:
Open(stack, optionsScene);
break;
}
}
private static void FindHost(out MenuSceneStack stack, out MenuScene hostScene, out MenuScene optionsScene)
{
stack = null;
hostScene = null;
optionsScene = null;
MidgameUI val = Object.FindFirstObjectByType<MidgameUI>((FindObjectsInactive)1);
if ((Object)(object)val != (Object)null)
{
optionsScene = val.OptionsScene;
hostScene = ((Component)val).GetComponentInParent<MenuScene>(true);
stack = ((Component)val).GetComponentInParent<MenuSceneStack>(true);
return;
}
MainMenuUI val2 = Object.FindFirstObjectByType<MainMenuUI>((FindObjectsInactive)1);
if ((Object)(object)val2 != (Object)null)
{
optionsScene = val2.OptionsScene;
hostScene = ((Component)val2).GetComponentInParent<MenuScene>(true);
stack = ((Component)val2).GetComponentInParent<MenuSceneStack>(true);
}
}
private static bool OtherMenuOpen(MenuSceneStack stack, MenuScene hostScene, MenuScene optionsScene)
{
if (OpenStacks?.GetValue(null) is List<MenuSceneStack> list)
{
foreach (MenuSceneStack item in list)
{
if ((Object)(object)item != (Object)(object)stack)
{
return true;
}
}
}
MenuScene val = default(MenuScene);
if ((Object)(object)stack != (Object)null && MenuSceneManager.IsStackOpen(stack) && stack.TryGetActiveScene(ref val))
{
if ((Object)(object)val != (Object)(object)hostScene)
{
return (Object)(object)val != (Object)(object)optionsScene;
}
return false;
}
return false;
}
private static bool TextFieldFocused(OptionsUI options)
{
if ((Object)(object)options == (Object)null)
{
return false;
}
object obj;
if (!OptionsAccess.Ready)
{
obj = null;
}
else
{
VisualElement obj2 = OptionsAccess.Root(options);
object obj3;
if (obj2 == null)
{
obj3 = null;
}
else
{
IPanel panel = obj2.panel;
if (panel == null)
{
obj3 = null;
}
else
{
FocusController focusController = panel.focusController;
obj3 = ((focusController != null) ? focusController.focusedElement : null);
}
}
obj = ((obj3 is VisualElement) ? obj3 : null);
}
VisualElement val = (VisualElement)obj;
if (!(val is TextField))
{
return ((val != null) ? val.GetFirstAncestorOfType<TextField>() : null) != null;
}
return true;
}
private static void Open(MenuSceneStack stack, MenuScene optionsScene)
{
RestoreFocusName();
_focusSwapped = optionsScene;
_originalFocusName = optionsScene.DefaultFocusElementName;
optionsScene.DefaultFocusElementName = "ModsTabBtn";
ModsTabInstaller.OpenOnModsPending = true;
try
{
stack.PushActiveScene(optionsScene);
}
finally
{
ModsTabInstaller.OpenOnModsPending = false;
}
}
internal static void RestoreFocusName()
{
if (!((Object)(object)_focusSwapped == (Object)null))
{
_focusSwapped.DefaultFocusElementName = _originalFocusName;
_focusSwapped = null;
_originalFocusName = null;
}
}
}
internal enum HotkeyAction
{
None,
ShowModsTab,
OpenOptions
}
internal struct HotkeyState
{
public bool OptionsActive;
public bool TextFieldFocused;
public bool Rebinding;
public bool Loading;
public bool MenusSuppressed;
public bool HasMenuHost;
public bool OtherMenuOpen;
}
internal static class HotkeyGate
{
public static HotkeyAction Decide(HotkeyState s)
{
if (s.TextFieldFocused || s.Rebinding || s.Loading || s.MenusSuppressed || s.OtherMenuOpen)
{
return HotkeyAction.None;
}
if (s.OptionsActive)
{
return HotkeyAction.ShowModsTab;
}
if (!s.HasMenuHost)
{
return HotkeyAction.None;
}
return HotkeyAction.OpenOptions;
}
}
internal static class KeyNames
{
private static readonly (string KeyCode, string Key)[] Renamed = new(string, string)[16]
{
("Return", "Enter"),
("KeypadEnter", "NumpadEnter"),
("KeypadPlus", "NumpadPlus"),
("KeypadMinus", "NumpadMinus"),
("KeypadMultiply", "NumpadMultiply"),
("KeypadDivide", "NumpadDivide"),
("KeypadPeriod", "NumpadPeriod"),
("KeypadEquals", "NumpadEquals"),
("LeftControl", "LeftCtrl"),
("RightControl", "RightCtrl"),
("LeftCommand", "LeftMeta"),
("RightCommand", "RightMeta"),
("BackQuote", "Backquote"),
("Print", "PrintScreen"),
("Numlock", "NumLock"),
("Menu", "ContextMenu")
};
private static readonly string[] Modifiers = new string[9] { "LeftControl", "RightControl", "LeftShift", "RightShift", "LeftAlt", "RightAlt", "LeftCommand", "RightCommand", "AltGr" };
public static string ToKeyName(string keyCode)
{
(string, string)[] renamed = Renamed;
for (int i = 0; i < renamed.Length; i++)
{
var (text, result) = renamed[i];
if (text == keyCode)
{
return result;
}
}
if (keyCode.StartsWith("Alpha", StringComparison.Ordinal))
{
return "Digit" + keyCode.Substring("Alpha".Length);
}
if (keyCode.StartsWith("Keypad", StringComparison.Ordinal))
{
return "Numpad" + keyCode.Substring("Keypad".Length);
}
return keyCode;
}
public static string ToKeyCodeName(string key)
{
(string, string)[] renamed = Renamed;
for (int i = 0; i < renamed.Length; i++)
{
(string, string) tuple = renamed[i];
var (result, _) = tuple;
if (tuple.Item2 == key)
{
return result;
}
}
if (key.StartsWith("Digit", StringComparison.Ordinal))
{
return "Alpha" + key.Substring("Digit".Length);
}
if (key.StartsWith("Numpad", StringComparison.Ordinal))
{
return "Keypad" + key.Substring("Numpad".Length);
}
return key;
}
public static bool IsModifier(string keyCode)
{
return Array.IndexOf(Modifiers, keyCode) >= 0;
}
}
internal static class KeyRebind
{
private static Button _listening;
private static Func<object, bool> _set;
private static Action _restore;
private static int _startFrame;
private static int _cancelledFrame = -10;
public static bool Listening => _listening != null;
public static bool ConsumesCancel
{
get
{
if (_listening == null)
{
return Time.frameCount - _cancelledFrame <= 1;
}
return true;
}
}
public unsafe static Button Create(SettingRow row, ConfigEntryBase entry, Func<object, bool> set, out Action refresh)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
VisualElement val = new VisualElement();
val.AddToClassList("cycle-control");
Button button = new Button();
((VisualElement)button).AddToClassList("options-text");
((VisualElement)button).AddToClassList("cycle-btn");
((VisualElement)button).AddToClassList("cycle-btn-single");
Action update = delegate
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (_listening != button)
{
KeyboardShortcut val2 = (KeyboardShortcut)entry.BoxedValue;
((TextElement)button).text = (((int)((KeyboardShortcut)(ref val2)).MainKey == 0) ? "Not bound" : ((object)(*(KeyboardShortcut*)(&val2))/*cast due to .constrained prefix*/).ToString());
}
};
button.clicked += delegate
{
if (_listening != button)
{
Cancel();
_listening = button;
_set = set;
_restore = update;
_startFrame = Time.frameCount;
((TextElement)button).text = "Press a key…";
}
};
((CallbackEventHandler)button).RegisterCallback<DetachFromPanelEvent>((EventCallback<DetachFromPanelEvent>)delegate
{
if (_listening == button)
{
Cancel();
}
}, (TrickleDown)0);
val.Add((VisualElement)(object)button);
((VisualElement)row).Add(val);
update();
refresh = update;
return button;
}
public static void Cancel()
{
if (_listening != null)
{
Action restore = _restore;
End();
restore?.Invoke();
}
}
public unsafe static void Tick()
{
//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_004c: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Invalid comparison between Unknown and I4
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
if (_listening == null)
{
return;
}
if (((VisualElement)_listening).panel == null)
{
Cancel();
return;
}
Keyboard current = Keyboard.current;
if (current == null || Time.frameCount == _startFrame)
{
return;
}
if (((ButtonControl)current.escapeKey).wasPressedThisFrame)
{
Cancel();
return;
}
Enumerator<KeyControl> enumerator = current.allKeys.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
KeyControl current2 = enumerator.Current;
if (current2 != null && ((ButtonControl)current2).wasPressedThisFrame && Hotkey.TryGetKeyCode(current2.keyCode, out var code) && !KeyNames.IsModifier(((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString()))
{
Func<object, bool> set = _set;
Action restore = _restore;
End();
set((object)(KeyboardShortcut)(((int)code == 8) ? KeyboardShortcut.Empty : new KeyboardShortcut(code, HeldModifiers(current))));
restore();
break;
}
}
}
finally
{
((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
}
}
private static void End()
{
_listening = null;
_set = null;
_restore = null;
_cancelledFrame = Time.frameCount;
}
private static KeyCode[] HeldModifiers(Keyboard keyboard)
{
List<KeyCode> list = new List<KeyCode>();
if (((ButtonControl)keyboard.leftCtrlKey).isPressed)
{
list.Add((KeyCode)306);
}
if (((ButtonControl)keyboard.rightCtrlKey).isPressed)
{
list.Add((KeyCode)305);
}
if (((ButtonControl)keyboard.leftShiftKey).isPressed)
{
list.Add((KeyCode)304);
}
if (((ButtonControl)keyboard.rightShiftKey).isPressed)
{
list.Add((KeyCode)303);
}
if (((ButtonControl)keyboard.leftAltKey).isPressed)
{
list.Add((KeyCode)308);
}
if (((ButtonControl)keyboard.rightAltKey).isPressed)
{
list.Add((KeyCode)307);
}
if (((ButtonControl)keyboard.leftMetaKey).isPressed)
{
list.Add((KeyCode)310);
}
if (((ButtonControl)keyboard.rightMetaKey).isPressed)
{
list.Add((KeyCode)309);
}
return list.ToArray();
}
}
internal sealed class ModsTab
{
private static string _rememberedGuid;
private static readonly HashSet<string> LoggedRows = new HashSet<string>();
private readonly VisualElement _container;
private readonly VisualElement _skinRoot;
private readonly Action<VisualElement, VisualElement> _wireEdges;
private readonly List<Action> _refreshers = new List<Action>();
private List<ModInfo> _mods = new List<ModInfo>();
private ModInfo _selected;
private Button _picker;
public ModsTab(VisualElement container, VisualElement skinRoot, Action<VisualElement, VisualElement> wireEdges)
{
_container = container;
_skinRoot = skinRoot;
_wireEdges = wireEdges;
}
public void Rebuild()
{
_mods = SettingsRegistry.Collect();
Render();
}
public void ResetSelectedMod()
{
if (_selected == null)
{
return;
}
foreach (SettingInfo setting in _selected.Settings)
{
if (!setting.Hidden && !setting.ReadOnly)
{
ConfigWriter.Set(setting.Entry, setting.Entry.DefaultValue);
}
}
RefreshAll();
}
private void Select(int index)
{
_rememberedGuid = _mods[Picker.Wrap(index, _mods.Count)].Guid;
Render();
Button picker = _picker;
if (picker != null)
{
((Focusable)picker).Focus();
}
}
private void Render()
{
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: 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_0203: Unknown result type (might be due to invalid IL or missing references)
KeyRebind.Cancel();
_container.Clear();
_refreshers.Clear();
_picker = null;
_selected = null;
if (_mods.Count == 0)
{
Rows.Message(_container, "No installed mods have settings.");
_wireEdges(null, null);
return;
}
int index = Picker.IndexOf(_mods.Select((ModInfo m) => m.Guid).ToList(), _rememberedGuid);
_selected = _mods[index];
_rememberedGuid = _selected.Guid;
SettingRow val = Rows.Row("Mod", null);
ModInfo mod = _selected;
_picker = Rows.Cycle(val, () => mod.Name + " " + mod.Version, delegate
{
Select(index + 1);
}, delegate
{
Select(index - 1);
}, out var _);
_container.Add((VisualElement)(object)val);
foreach (SettingGroup<SettingInfo> item in SettingOrder.Group(_selected.Settings, (SettingInfo s) => s.Facts))
{
Rows.Heading(_container, item.Heading);
foreach (SettingInfo item2 in item.Items)
{
_refreshers.Add(BuildRow(item2));
}
}
VisualElement val2 = UQueryExtensions.Query<VisualElement>(_container, (string)null, (string)null).Where((Func<VisualElement, bool>)((VisualElement v) => ((Focusable)v).focusable && ((Focusable)v).canGrabFocus)).ToList()
.LastOrDefault();
_wireEdges((VisualElement)(object)_picker, (VisualElement)(((object)val2) ?? ((object)_picker)));
}
private Action BuildRow(SettingInfo setting)
{
int childCount = _container.childCount;
try
{
return SettingEditors.Build(_container, setting, _skinRoot, RefreshAll);
}
catch (Exception arg)
{
while (_container.childCount > childCount)
{
_container.RemoveAt(_container.childCount - 1);
}
SettingEditors.BuildBroken(_container, setting);
if (LoggedRows.Add($"{setting.Mod.Guid}/{setting.Entry.Definition}"))
{
Plugin.Log.LogWarning((object)$"Can't show {setting.Mod.Name} / {setting.Entry.Definition} in the Mods tab. {arg}");
}
return delegate
{
};
}
}
private void RefreshAll()
{
foreach (Action refresher in _refreshers)
{
refresher();
}
}
}
internal static class ModsTabInstaller
{
public const string ButtonName = "ModsTabBtn";
public const string ContentName = "ModsTab";
private static bool _warned;
public static bool OpenOnModsPending;
public static OptionsUI Active { get; private set; }
public static void Install(OptionsUI ui)
{
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
Active = ui;
if (!OptionsAccess.Ready)
{
return;
}
VisualElement val = OptionsAccess.Root(ui);
object obj;
if (val == null)
{
obj = null;
}
else
{
VisualElement obj2 = UQueryExtensions.Q<VisualElement>(val, "OptionsPanel", (string)null);
obj = ((obj2 != null) ? UQueryExtensions.Q<VisualElement>(obj2, (string)null, "content-area") : null);
}
if (obj == null)
{
obj = val;
}
VisualElement val2 = (VisualElement)obj;
Button val3 = ((val != null) ? UQueryExtensions.Q<Button>(val, "KeybindsTabBtn", (string)null) : null);
VisualElement val4 = ((val2 != null) ? UQueryExtensions.Q<VisualElement>(val2, "AudioTab", (string)null) : null);
if (val == null || val3 == null || val4 == null)
{
if (!_warned)
{
_warned = true;
Plugin.Log.LogWarning((object)"The Options screen layout changed (KeybindsTabBtn or AudioTab not found); the Mods tab is unavailable.");
}
return;
}
Button button = UQueryExtensions.Q<Button>(val, "ModsTabBtn", (string)null) ?? CreateButton(ui, val3);
VisualElement content = UQueryExtensions.Q<VisualElement>(val2, "ModsTab", (string)null) ?? CreateContent(val4);
if (((VisualElement)button).userData == null)
{
((VisualElement)button).userData = OptionsAccess.MakeTab(button, content, delegate
{
(content.userData as ModsTab)?.ResetSelectedMod();
});
WireButton(ui, button, content);
}
object userData = ((VisualElement)button).userData;
OptionsAccess.AppendTab(ui, userData);
content.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
((VisualElement)button).RemoveFromClassList("tab-button--active");
VisualElement parent = ((VisualElement)button).parent;
if (parent != null)
{
parent.RemoveFromClassList("tab-button-container--active");
}
ModsTab modsTab = content.userData as ModsTab;
if (modsTab == null)
{
modsTab = new ModsTab((VisualElement)(object)UQueryExtensions.Q<ScrollView>(content, (string)null, (string)null), val, delegate(VisualElement first, VisualElement last)
{
if (first != null)
{
OptionsAccess.SetNav(ui, first, (Direction)2, (VisualElement _) => (VisualElement)(object)button);
}
if (last != null)
{
OptionsAccess.SetNav(ui, last, (Direction)4, (VisualElement _) => (VisualElement)(object)OptionsAccess.ResetButton(ui));
}
});
content.userData = modsTab;
}
modsTab.Rebuild();
if (OpenOnModsPending)
{
OpenOnModsPending = false;
OptionsAccess.ClickTab(ui, userData);
}
}
public static void Closed(OptionsUI ui)
{
KeyRebind.Cancel();
ConfigWriter.Flush();
HotkeyController.RestoreFocusName();
if ((Object)(object)Active == (Object)(object)ui)
{
Active = null;
}
}
public static void ShowMods(OptionsUI ui)
{
VisualElement obj = OptionsAccess.Root(ui);
object obj2;
if (obj == null)
{
obj2 = null;
}
else
{
Button obj3 = UQueryExtensions.Q<Button>(obj, "ModsTabBtn", (string)null);
obj2 = ((obj3 != null) ? ((VisualElement)obj3).userData : null);
}
object obj4 = obj2;
if (obj4 != null)
{
OptionsAccess.ClickTab(ui, obj4);
}
}
private static Button CreateButton(OptionsUI ui, Button template)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
Button val = new Button
{
name = "ModsTabBtn"
};
CopyClasses((VisualElement)(object)template, (VisualElement)(object)val, "tab-button--active");
if (!string.IsNullOrEmpty(((TextElement)template).text))
{
((TextElement)val).text = "Mods";
}
else
{
Label val2 = UQueryExtensions.Q<Label>((VisualElement)(object)template, (string)null, (string)null);
Label val3 = new Label("Mods");
if (val2 != null)
{
CopyClasses((VisualElement)(object)val2, (VisualElement)(object)val3);
}
((VisualElement)val).Add((VisualElement)(object)val3);
}
VisualElement parent = ((VisualElement)template).parent;
if (parent != null && parent.parent != null && UQueryExtensions.Query<Button>(parent, (string)null, (string)null).ToList().Count == 1)
{
VisualElement val4 = new VisualElement();
CopyClasses(parent, val4, "tab-button-container--active", "tab-button-container--focused");
val4.Add((VisualElement)(object)val);
parent.parent.Insert(parent.parent.IndexOf(parent) + 1, val4);
}
else if (parent != null)
{
parent.Insert(parent.IndexOf((VisualElement)(object)template) + 1, (VisualElement)(object)val);
}
return val;
}
private static void WireButton(OptionsUI ui, Button button, VisualElement content)
{
button.clicked += delegate
{
OptionsAccess.ClickTab(ui, ((VisualElement)button).userData);
};
((CallbackEventHandler)button).RegisterCallback<FocusInEvent>((EventCallback<FocusInEvent>)delegate
{
OptionsAccess.TabButtonFocused(ui, ((VisualElement)button).userData);
VisualElement parent = ((VisualElement)button).parent;
if (parent != null)
{
parent.AddToClassList("tab-button-container--focused");
}
}, (TrickleDown)0);
((CallbackEventHandler)button).RegisterCallback<FocusOutEvent>((EventCallback<FocusOutEvent>)delegate
{
VisualElement parent = ((VisualElement)button).parent;
if (parent != null)
{
parent.RemoveFromClassList("tab-button-container--focused");
}
}, (TrickleDown)0);
OptionsAccess.SetNav(ui, (VisualElement)(object)button, (Direction)2, (VisualElement _) => Focusables(content).LastOrDefault());
OptionsAccess.SetNav(ui, (VisualElement)(object)button, (Direction)4, (VisualElement _) => Focusables(content).FirstOrDefault());
}
private static VisualElement CreateContent(VisualElement template)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Expected O, but got Unknown
//IL_005c: 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_0073: Unknown result type (might be due to invalid IL or missing references)
VisualElement val = new VisualElement
{
name = "ModsTab"
};
CopyClasses(template, val);
val.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
ScrollView scroll = new ScrollView((ScrollViewMode)0);
scroll.horizontalScrollerVisibility = (ScrollerVisibility)2;
((VisualElement)scroll).style.flexGrow = StyleFloat.op_Implicit(1f);
foreach (VisualElement item in UQueryExtensions.Query<VisualElement>((VisualElement)(object)scroll, (string)null, (string)null).ToList())
{
if ((object)item != scroll && item != ((VisualElement)scroll).contentContainer)
{
((Focusable)item).focusable = false;
}
}
((CallbackEventHandler)scroll).RegisterCallback<FocusInEvent>((EventCallback<FocusInEvent>)delegate(FocusInEvent e)
{
IEventHandler target = ((EventBase)e).target;
VisualElement val2 = (VisualElement)(object)((target is VisualElement) ? target : null);
if (val2 != null && (object)val2 != scroll && ((VisualElement)scroll).contentContainer.Contains(val2))
{
scroll.ScrollTo(val2);
}
}, (TrickleDown)1);
val.Add((VisualElement)(object)scroll);
template.parent.Insert(template.parent.IndexOf(template) + 1, val);
return val;
}
private static List<VisualElement> Focusables(VisualElement container)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
return UQueryExtensions.Query<VisualElement>(container, (string)null, (string)null).Where((Func<VisualElement, bool>)((VisualElement v) => ((Focusable)v).focusable && ((Focusable)v).canGrabFocus)).ToList();
}
private static void CopyClasses(VisualElement from, VisualElement to, params string[] except)
{
foreach (string @class in from.GetClasses())
{
if (!@class.StartsWith("unity-", StringComparison.Ordinal) && Array.IndexOf(except, @class) < 0)
{
to.AddToClassList(@class);
}
}
}
}
internal static class Names
{
public static string Humanize(string key)
{
if (string.IsNullOrEmpty(key) || key.Contains(" "))
{
return key;
}
List<char> list = new List<char>(key.Length + 8);
for (int i = 0; i < key.Length; i++)
{
char c = key[i];
if (c == '_')
{
list.Add(' ');
continue;
}
if (i > 0 && char.IsUpper(c) && key[i - 1] != '_' && (char.IsLower(key[i - 1]) || (i + 1 < key.Length && char.IsLower(key[i + 1]) && char.IsUpper(key[i - 1]))))
{
list.Add(' ');
}
list.Add(c);
}
return new string(list.ToArray());
}
}
internal static class OptionsAccess
{
private static Type _tabType;
private static FieldInfo _tabButton;
private static FieldInfo _tabContent;
private static FieldInfo _tabReset;
private static FieldInfo _tabs;
private static FieldInfo _root;
private static FieldInfo _currentTab;
private static FieldInfo _resetButton;
private static MethodInfo _clickTab;
private static MethodInfo _tabButtonFocused;
private static MethodInfo _setNav;
public static bool Ready { get; private set; }
public static bool Init()
{
Type typeFromHandle = typeof(OptionsUI);
_tabType = typeFromHandle.GetNestedType("Tab", BindingFlags.Public | BindingFlags.NonPublic);
_tabButton = _tabType?.GetField("Button", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_tabContent = _tabType?.GetField("Content", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_tabReset = _tabType?.GetField("ResetDefaults", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_tabs = typeFromHandle.GetField("_tabs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_root = typeFromHandle.GetField("_root", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_currentTab = typeFromHandle.GetField("_currentTab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_resetButton = typeFromHandle.GetField("_resetDefaultsBtn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_clickTab = ((_tabType == null) ? null : typeFromHandle.GetMethod("ClickTab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { _tabType }, null));
_tabButtonFocused = ((_tabType == null) ? null : typeFromHandle.GetMethod("OnTabButtonFocused", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { _tabType }, null));
_setNav = typeFromHandle.GetMethod("SetDirectionalNavForElement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
List<string> missing = new List<string>();
Check(_tabType, "Tab");
Check(_tabButton, "Tab.Button");
Check(_tabContent, "Tab.Content");
Check(_tabReset, "Tab.ResetDefaults");
Check(_tabs, "_tabs");
Check(_root, "_root");
Check(_currentTab, "_currentTab");
Check(_resetButton, "_resetDefaultsBtn");
Check(_clickTab, "ClickTab");
Check(_tabButtonFocused, "OnTabButtonFocused");
Check(_setNav, "SetDirectionalNavForElement");
Ready = missing.Count == 0;
if (!Ready)
{
Plugin.Log.LogWarning((object)("The Options screen changed (" + string.Join(", ", missing) + " not found); the Mods tab is unavailable."));
}
return Ready;
void Check(object member, string name)
{
if (member == null)
{
missing.Add(name);
}
}
}
public static VisualElement Root(OptionsUI ui)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return (VisualElement)_root.GetValue(ui);
}
public static Button ResetButton(OptionsUI ui)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return (Button)_resetButton.GetValue(ui);
}
public static object MakeTab(Button button, VisualElement content, Action resetDefaults)
{
object obj = Activator.CreateInstance(_tabType);
_tabButton.SetValue(obj, button);
_tabContent.SetValue(obj, content);
_tabReset.SetValue(obj, resetDefaults);
return obj;
}
public static void AppendTab(OptionsUI ui, object tab)
{
Array array = (Array)_tabs.GetValue(ui);
object value = _tabContent.GetValue(tab);
foreach (object item in array)
{
if (_tabContent.GetValue(item) == value)
{
return;
}
}
Array array2 = Array.CreateInstance(_tabType, array.Length + 1);
Array.Copy(array, array2, array.Length);
array2.SetValue(tab, array.Length);
_tabs.SetValue(ui, array2);
}
public static bool IsCurrent(OptionsUI ui, VisualElement content)
{
return _tabContent.GetValue(_currentTab.GetValue(ui)) == content;
}
public static void ClickTab(OptionsUI ui, object tab)
{
_clickTab.Invoke(ui, new object[1] { tab });
}
public static void TabButtonFocused(OptionsUI ui, object tab)
{
_tabButtonFocused.Invoke(ui, new object[1] { tab });
}
public static void SetNav(OptionsUI ui, VisualElement element, Direction direction, Func<VisualElement, VisualElement> next)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
_setNav.Invoke(ui, new object[3] { element, direction, next });
}
}
internal static class Picker
{
public static int Wrap(int index, int count)
{
if (count > 0)
{
return (index % count + count) % count;
}
return -1;
}
public static int IndexOf(IReadOnlyList<string> ids, string remembered)
{
if (ids.Count == 0)
{
return -1;
}
for (int i = 0; i < ids.Count; i++)
{
if (string.Equals(ids[i], remembered, StringComparison.Ordinal))
{
return i;
}
}
return 0;
}
}
[BepInPlugin("com.darkharasho.trashday.modsettings", "ModSettings", "0.1.1")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "com.darkharasho.trashday.modsettings";
public const string PluginName = "ModSettings";
public const string PluginVersion = "0.1.1";
internal static ManualLogSource Log;
internal static ConfigEntry<KeyboardShortcut> OpenKey;
private Harmony _harmony;
private void Awake()
{
//IL_0025: 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_0053: Expected O, but got Unknown
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Expected O, but got Unknown
//IL_00ae: 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)
Log = ((BaseUnityPlugin)this).Logger;
OpenKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "OpenKey", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), new ConfigDescription("Opens the game's Options screen on the Mods tab.", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
DispName = "Open key"
}
}));
_harmony = new Harmony("com.darkharasho.trashday.modsettings");
try
{
_harmony.PatchAll();
}
catch (Exception arg)
{
Log.LogError((object)$"Patching failed, likely a game update; the Mods tab is unavailable. {arg}");
_harmony.UnpatchSelf();
return;
}
OptionsAccess.Init();
GameObject val = new GameObject("ModSettings");
Object.DontDestroyOnLoad((Object)val);
((Object)val).hideFlags = (HideFlags)61;
val.AddComponent<HotkeyController>();
Log.LogInfo((object)string.Format("{0} {1} loaded; press {2} for the Mods tab", "ModSettings", "0.1.1", OpenKey.Value));
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
internal static class Rows
{
public static SettingRow Row(string label, string description)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0023: 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_0039: Expected O, but got Unknown
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Expected O, but got Unknown
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
SettingRow val = new SettingRow();
VisualElement val2 = new VisualElement();
val2.AddToClassList("setting-label");
val2.style.flexDirection = StyleEnum<FlexDirection>.op_Implicit((FlexDirection)0);
Label name = new Label(label);
((VisualElement)name).AddToClassList("options-text");
val2.Add((VisualElement)(object)name);
if (!string.IsNullOrEmpty(description))
{
Label note = new Label(description);
((VisualElement)note).AddToClassList("options-text");
((VisualElement)note).style.whiteSpace = StyleEnum<WhiteSpace>.op_Implicit((WhiteSpace)0);
((VisualElement)note).style.opacity = StyleFloat.op_Implicit(0.7f);
((CallbackEventHandler)name).RegisterCallback<GeometryChangedEvent>((EventCallback<GeometryChangedEvent>)delegate
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
float num = ((VisualElement)name).resolvedStyle.fontSize * 0.6f;
if (num > 0f && Math.Abs(((VisualElement)note).resolvedStyle.fontSize - num) > 0.5f)
{
((VisualElement)note).style.fontSize = StyleLength.op_Implicit(num);
}
}, (TrickleDown)0);
val2.Add((VisualElement)(object)note);
}
((VisualElement)val).Add(val2);
return val;
}
public static Button Cycle(SettingRow row, Func<string> text, Action next, Action previous, out Action refresh)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
VisualElement val = new VisualElement();
val.AddToClassList("cycle-control");
Button button = new Button();
((VisualElement)button).AddToClassList("options-text");
((VisualElement)button).AddToClassList("cycle-btn");
((VisualElement)button).AddToClassList("cycle-btn-single");
Action update = delegate
{
((TextElement)button).text = text();
};
button.clicked += delegate
{
next();
update();
};
((CallbackEventHandler)button).RegisterCallback<NavigationMoveEvent>((EventCallback<NavigationMoveEvent>)delegate(NavigationMoveEvent evt)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Invalid comparison between Unknown and I4
if ((int)evt.direction == 1 || (int)evt.direction == 3)
{
IPanel panel = ((VisualElement)button).panel;
FocusController obj = ((panel != null) ? panel.focusController : null);
if ((int)evt.direction == 1)
{
previous();
}
else
{
next();
}
update();
((EventBase)evt).StopPropagation();
if (obj != null)
{
obj.IgnoreEvent((EventBase)(object)evt);
}
}
}, (TrickleDown)0);
val.Add((VisualElement)(object)button);
((VisualElement)row).Add(val);
update();
refresh = update;
return button;
}
public static Slider Slider(SettingRow row, float low, float high, bool integer, Func<float> get, Action<float> set, out Action refresh)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Expected O, but got Unknown
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
VisualElement val = new VisualElement();
val.AddToClassList("setting-control");
Label valueLabel = new Label();
((VisualElement)valueLabel).AddToClassList("options-text");
((VisualElement)valueLabel).AddToClassList("slider-value-label");
Slider slider = new Slider(low, high, (SliderDirection)0, 0f);
((VisualElement)slider).AddToClassList("setting-slider");
INotifyValueChangedExtensions.RegisterValueChangedCallback<float>((INotifyValueChanged<float>)(object)slider, (EventCallback<ChangeEvent<float>>)delegate(ChangeEvent<float> e)
{
float num = (integer ? ((float)ValueParsing.SnapInteger(e.newValue)) : ValueParsing.RoundToStep(e.newValue, low, high));
((BaseField<float>)(object)slider).SetValueWithoutNotify(num);
((TextElement)valueLabel).text = ValueParsing.FormatSlider(num, integer);
if (!Mathf.Approximately(num, get()))
{
set(num);
}
});
val.Add((VisualElement)(object)valueLabel);
val.Add((VisualElement)(object)slider);
((VisualElement)row).Add(val);
refresh = delegate
{
float num = get();
((BaseField<float>)(object)slider).SetValueWithoutNotify(num);
((TextElement)valueLabel).text = ValueParsing.FormatSlider(num, integer);
};
refresh();
return slider;
}
public static DropdownField Dropdown(SettingRow row, List<string> labels, Func<int> getIndex, Func<string> currentLabel, Action<int> setIndex, VisualElement skinRoot, out Action refresh)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
DropdownField dropdown = new DropdownField(labels, -1, (Func<string, string>)null, (Func<string, string>)null);
((VisualElement)dropdown).AddToClassList("options-text");
((VisualElement)dropdown).AddToClassList("setting-dropdown");
((CallbackEventHandler)dropdown).RegisterCallback<PointerDownEvent>((EventCallback<PointerDownEvent>)delegate
{
skinRoot.schedule.Execute((Action)delegate
{
SkinOpenDropdown(skinRoot);
});
}, (TrickleDown)0);
((CallbackEventHandler)dropdown).RegisterCallback<NavigationSubmitEvent>((EventCallback<NavigationSubmitEvent>)delegate
{
skinRoot.schedule.Execute((Action)delegate
{
SkinOpenDropdown(skinRoot);
});
}, (TrickleDown)0);
INotifyValueChangedExtensions.RegisterValueChangedCallback<string>((INotifyValueChanged<string>)(object)dropdown, (EventCallback<ChangeEvent<string>>)delegate
{
int num = labels.IndexOf(((BaseField<string>)(object)dropdown).value);
if (num >= 0)
{
setIndex(num);
}
});
((VisualElement)row).Add((VisualElement)(object)dropdown);
refresh = delegate
{
int num = getIndex();
((BaseField<string>)(object)dropdown).SetValueWithoutNotify((num >= 0) ? labels[num] : currentLabel());
};
refresh();
return dropdown;
}
private static void SkinOpenDropdown(VisualElement skinRoot)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
IPanel panel = skinRoot.panel;
VisualElement val = ((panel != null) ? UQueryExtensions.Q(panel.visualTree, (string)null, "unity-base-dropdown") : null);
if (val == null || val.ClassListContains("trash-dropdown-skinned"))
{
return;
}
val.AddToClassList("trash-dropdown-skinned");
int num = 0;
while (true)
{
int num2 = num;
VisualElementStyleSheetSet styleSheets = skinRoot.styleSheets;
if (num2 < ((VisualElementStyleSheetSet)(ref styleSheets)).count)
{
styleSheets = val.styleSheets;
VisualElementStyleSheetSet styleSheets2 = skinRoot.styleSheets;
((VisualElementStyleSheetSet)(ref styleSheets)).Add(((VisualElementStyleSheetSet)(ref styleSheets2))[num]);
num++;
continue;
}
break;
}
}
public static TextField Text(SettingRow row, Func<string> get, Func<string, bool> commit, out Action refresh)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0037: Expected O, but got Unknown
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
VisualElement val = new VisualElement();
val.AddToClassList("setting-control");
TextField val2 = new TextField();
((TextInputBaseField<string>)val2).isDelayed = true;
TextField field = val2;
((VisualElement)field).AddToClassList("options-text");
((VisualElement)field).style.flexGrow = StyleFloat.op_Implicit(1f);
Action update = delegate
{
((BaseField<string>)(object)field).SetValueWithoutNotify(get());
};
INotifyValueChangedExtensions.RegisterValueChangedCallback<string>((INotifyValueChanged<string>)(object)field, (EventCallback<ChangeEvent<string>>)delegate(ChangeEvent<string> e)
{
if (!commit(e.newValue))
{
update();
}
});
val.Add((VisualElement)(object)field);
((VisualElement)row).Add(val);
update();
refresh = update;
return field;
}
public static Label ReadOnly(SettingRow row, Func<string> text, out Action refresh)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Expected O, but got Unknown
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
VisualElement val = new VisualElement();
val.AddToClassList("setting-control");
Label label = new Label();
((VisualElement)label).AddToClassList("options-text");
((VisualElement)label).style.opacity = StyleFloat.op_Implicit(0.7f);
val.Add((VisualElement)(object)label);
((VisualElement)row).Add(val);
Action action = delegate
{
((TextElement)label).text = text();
};
action();
refresh = action;
return label;
}
public static Label Note(SettingRow row, string text)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
Label val = new Label(text);
((VisualElement)val).AddToClassList("options-text");
((VisualElement)val).style.opacity = StyleFloat.op_Implicit(0.7f);
((VisualElement)val).style.marginLeft = StyleLength.op_Implicit(12f);
((VisualElement)val).style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
((VisualElement)row).Add((VisualElement)(object)val);
return val;
}
public static void Heading(VisualElement parent, string text)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
Label val = new Label(text);
((VisualElement)val).AddToClassList("options-text");
((VisualElement)val).style.unityFontStyleAndWeight = StyleEnum<FontStyle>.op_Implicit((FontStyle)1);
((VisualElement)val).style.marginTop = StyleLength.op_Implicit(18f);
((VisualElement)val).style.marginBottom = StyleLength.op_Implicit(6f);
parent.Add((VisualElement)(object)val);
}
public static void Message(VisualElement parent, string text)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected O, but got Unknown
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
Label val = new Label(text);
((VisualElement)val).AddToClassList("options-text");
((VisualElement)val).style.marginTop = StyleLength.op_Implicit(24f);
((VisualElement)val).style.unityTextAlign = StyleEnum<TextAnchor>.op_Implicit((TextAnchor)4);
parent.Add((VisualElement)(object)val);
}
}
internal sealed class SaveSchedule
{
private readonly float _interval;
private float _due;
public bool Dirty { get; private set; }
public SaveSchedule(float interval = 1f)
{
_interval = interval;
}
public void MarkDirty(float now)
{
if (!Dirty)
{
Dirty = true;
_due = now + _interval;
}
}
public bool ShouldSave(float now)
{
if (Dirty)
{
return now >= _due;
}
return false;
}
public void Saved()
{
Dirty = false;
}
}
internal static class SettingEditors
{
public static Action Build(VisualElement parent, SettingInfo setting, VisualElement skinRoot, Action changed)
{
ConfigEntryBase entry = setting.Entry;
Type type = entry.SettingType;
ConfigDescription description = entry.Description;
AcceptableValueBase acceptable = ((description != null) ? description.AcceptableValues : null);
SettingRow val = Rows.Row(setting.Name, setting.Description);
Label restart = null;
Func<object, bool> set = delegate(object value)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (!ConfigWriter.Set(entry, value))
{
changed();
return false;
}
if (restart != null)
{
((VisualElement)restart).style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)0);
}
changed();
return true;
};
List<object> list = ListValues(acceptable);
EditorKind editorKind = EditorKinds.Choose(type, type == typeof(KeyboardShortcut), (list != null) ? Acceptable.List : (IsRange(acceptable) ? Acceptable.Range : Acceptable.None), list?.Count ?? 0);
Action refresh;
switch (editorKind)
{
case EditorKind.Toggle:
Rows.Cycle(val, () => (!(bool)entry.BoxedValue) ? "Off" : "On", delegate
{
set(!(bool)entry.BoxedValue);
}, delegate
{
set(!(bool)entry.BoxedValue);
}, out refresh);
break;
case EditorKind.Cycle:
{
List<object> choices2 = list ?? Enum.GetValues(type).Cast<object>().ToList();
Rows.Cycle(val, () => Label(entry.BoxedValue, type), delegate
{
set(choices2[Picker.Wrap(IndexOf(choices2, entry.BoxedValue) + 1, choices2.Count)]);
}, delegate
{
set(choices2[Picker.Wrap(IndexOf(choices2, entry.BoxedValue) - 1, choices2.Count)]);
}, out refresh);
break;
}
case EditorKind.Dropdown:
{
List<object> choices = list ?? Enum.GetValues(type).Cast<object>().ToList();
List<string> labels = choices.Select((object c) => Label(c, type)).ToList();
Rows.Dropdown(val, labels, () => IndexOf(choices, entry.BoxedValue), () => Label(entry.BoxedValue, type), delegate(int i)
{
set(choices[i]);
}, skinRoot, out refresh);
break;
}
case EditorKind.SliderInt:
case EditorKind.Slider:
{
(object Min, object Max) tuple = Range(acceptable);
object item = tuple.Min;
object item2 = tuple.Max;
bool integer = editorKind == EditorKind.SliderInt;
Rows.Slider(val, Convert.ToSingle(item, CultureInfo.InvariantCulture), Convert.ToSingle(item2, CultureInfo.InvariantCulture), integer, () => Convert.ToSingle(entry.BoxedValue, CultureInfo.InvariantCulture), delegate(float v)
{
set(Convert.ChangeType(integer ? ValueParsing.SnapInteger(v) : ((double)v), type, CultureInfo.InvariantCulture));
}, out refresh);
break;
}
case EditorKind.NumberText:
{
Rows.Text(val, () => ValueParsing.Format(entry.BoxedValue), (string text) => ValueParsing.TryParseNumber(text, type, out var value) && set(value), out refresh);
break;
}
case EditorKind.Text:
Rows.Text(val, () => ((string)entry.BoxedValue) ?? "", (string text) => set(text), out refresh);
break;
case EditorKind.Key:
KeyRebind.Create(val, entry, set, out refresh);
break;
default:
Rows.ReadOnly(val, () => entry.GetSerializedValue() + " (edit in the config file)", out refresh);
break;
}
if (setting.RestartRequired)
{
restart = Rows.Note(val, "restart needed");
}
if (setting.ReadOnly)
{
((VisualElement)val).SetEnabled(false);
}
parent.Add((VisualElement)(object)val);
return refresh;
}
public static void BuildBroken(VisualElement parent, SettingInfo setting)
{
SettingRow val = Rows.Row(setting.Name, setting.Description);
Rows.ReadOnly(val, () => "can't edit here", out var _);
parent.Add((VisualElement)(object)val);
}
private static List<object> ListValues(AcceptableValueBase acceptable)
{
Type type = ((object)acceptable)?.GetType();
if (type == null || !type.IsGenericType || type.GetGenericTypeDefinition() != typeof(AcceptableValueList<>))
{
return null;
}
return ((Array)type.GetProperty("AcceptableValues").GetValue(acceptable)).Cast<object>().ToList();
}
private static bool IsRange(AcceptableValueBase acceptable)
{
Type type = ((object)acceptable)?.GetType();
if (type != null && type.IsGenericType)
{
return type.GetGenericTypeDefinition() == typeof(AcceptableValueRange<>);
}
return false;
}
private static (object Min, object Max) Range(AcceptableValueBase acceptable)
{
Type type = ((object)acceptable).GetType();
return (Min: type.GetProperty("MinValue").GetValue(acceptable), Max: type.GetProperty("MaxValue").GetValue(acceptable));
}
private static int IndexOf(List<object> choices, object value)
{
for (int i = 0; i < choices.Count; i++)
{
if (object.Equals(choices[i], value))
{
return i;
}
}
return -1;
}
private static string Label(object value, Type type)
{
if (!type.IsEnum)
{
return TomlTypeConverter.ConvertToString(value, type);
}
return Names.Humanize(value.ToString());
}
}
internal struct SettingFacts
{
public string Section;
public string Name;
public int Order;
public bool Advanced;
public bool Hidden;
}
internal sealed class SettingGroup<T>
{
public string Heading;
public bool IsAdvanced;
public List<T> Items = new List<T>();
}
internal static class SettingOrder
{
public const string AdvancedHeading = "Advanced";
public static List<SettingGroup<T>> Group<T>(IEnumerable<T> items, Func<T, SettingFacts> facts)
{
List<SettingGroup<T>> list = new List<SettingGroup<T>>();
Dictionary<string, SettingGroup<T>> dictionary = new Dictionary<string, SettingGroup<T>>(StringComparer.Ordinal);
SettingGroup<T> settingGroup = new SettingGroup<T>
{
Heading = "Advanced",
IsAdvanced = true
};
foreach (T item in items)
{
SettingFacts settingFacts = facts(item);
if (settingFacts.Hidden)
{
continue;
}
if (settingFacts.Advanced)
{
settingGroup.Items.Add(item);
continue;
}
string text = settingFacts.Section ?? "";
if (!dictionary.TryGetValue(text, out var value))
{
value = new SettingGroup<T>
{
Heading = text
};
dictionary.Add(text, value);
list.Add(value);
}
value.Items.Add(item);
}
if (settingGroup.Items.Count > 0)
{
list.Add(settingGroup);
}
foreach (SettingGroup<T> item2 in list)
{
item2.Items = item2.Items.OrderByDescending((T i) => facts(i).Order).ThenBy<T, string>((T i) => facts(i).Name, StringComparer.OrdinalIgnoreCase).ToList();
}
return list;
}
public static bool AnyVisible<T>(IEnumerable<T> items, Func<T, SettingFacts> facts)
{
return items.Any((T i) => !facts(i).Hidden);
}
}
internal sealed class ModInfo
{
public string Guid;
public string Name;
public string Version;
public List<SettingInfo> Settings = new List<SettingInfo>();
}
internal sealed class SettingInfo
{
public ModInfo Mod;
public ConfigEntryBase Entry;
public string Section;
public string Name;
public string Description;
public int Order;
public bool ReadOnly;
public bool Advanced;
public bool Hidden;
public bool RestartRequired;
public SettingFacts Facts => new SettingFacts
{
Section = Section,
Name = Name,
Order = Order,
Advanced = Advanced,
Hidden = Hidden
};
}
internal static class SettingsRegistry
{
private const BindingFlags AnyField = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly HashSet<string> LoggedFailures = new HashSet<string>();
public static List<ModInfo> Collect()
{
List<ModInfo> list = new List<ModInfo>();
foreach (PluginInfo value in Chainloader.PluginInfos.Values)
{
if ((Object)(object)((value != null) ? value.Instance : null) == (Object)null)
{
continue;
}
try
{
ModInfo modInfo = new ModInfo
{
Guid = value.Metadata.GUID,
Name = value.Metadata.Name,
Version = value.Metadata.Version.ToString()
};
foreach (ConfigFile item in ConfigFiles(value.Instance))
{
foreach (ConfigEntryBase value2 in ((IDictionary<ConfigDefinition, ConfigEntryBase>)item).Values)
{
modInfo.Settings.Add(Describe(modInfo, value2));
}
}
if (SettingOrder.AnyVisible(modInfo.Settings, (SettingInfo s) => s.Facts))
{
list.Add(modInfo);
}
}
catch (Exception arg)
{
BepInPlugin metadata = value.Metadata;
string text = ((metadata != null) ? metadata.GUID : null) ?? "?";
if (LoggedFailures.Add(text))
{
Plugin.Log.LogWarning((object)$"Couldn't read the settings of {text}; it's left out of the Mods tab. {arg}");
}
}
}
return list.OrderBy<ModInfo, string>((ModInfo m) => m.Name, StringComparer.OrdinalIgnoreCase).ToList();
}
private static IEnumerable<ConfigFile> ConfigFiles(BaseUnityPlugin plugin)
{
HashSet<ConfigFile> seen = new HashSet<ConfigFile> { plugin.Config };
yield return plugin.Config;
Type type = ((object)plugin).GetType();
while (type != null && type != typeof(BaseUnityPlugin))
{
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (!(fieldInfo.FieldType != typeof(ConfigFile)))
{
BaseUnityPlugin obj = (fieldInfo.IsStatic ? null : plugin);
object? value = fieldInfo.GetValue(obj);
ConfigFile val = (ConfigFile)((value is ConfigFile) ? value : null);
if (val != null && seen.Add(val))
{
yield return val;
}
}
}
type = type.BaseType;
}
}
private static SettingInfo Describe(ModInfo mod, ConfigEntryBase entry)
{
SettingInfo obj = new SettingInfo
{
Mod = mod,
Entry = entry,
Section = entry.Definition.Section,
Name = Names.Humanize(entry.Definition.Key)
};
ConfigDescription description = entry.Description;
obj.Description = ((description != null) ? description.Description : null);
SettingInfo settingInfo = obj;
ConfigDescription description2 = entry.Description;
object[] array = ((description2 != null) ? description2.Tags : null);
if (array == null)
{
return settingInfo;
}
object[] array2 = array;
foreach (object obj2 in array2)
{
if (obj2 != null)
{
settingInfo.Hidden |= Read<bool?>(obj2, "Browsable") == false;
settingInfo.Section = Read<string>(obj2, "Category") ?? settingInfo.Section;
settingInfo.Name = Read<string>(obj2, "DispName") ?? settingInfo.Name;
settingInfo.Description = Read<string>(obj2, "Description") ?? settingInfo.Description;
settingInfo.Order = Read<int?>(obj2, "Order") ?? settingInfo.Order;
settingInfo.ReadOnly |= Read<bool?>(obj2, "ReadOnly") == true;
settingInfo.Advanced |= Read<bool?>(obj2, "IsAdvanced") == true;
settingInfo.RestartRequired |= Read<bool?>(obj2, "RestartRequired") == true;
}
}
return settingInfo;
}
private static T Read<T>(object tag, string name)
{
Type type = tag.GetType();
FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public);
object value;
if (field != null)
{
value = field.GetValue(tag);
}
else
{
PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
if (property == null || !property.CanRead)
{
return default(T);
}
value = property.GetValue(tag);
}
if (value is T)
{
return (T)value;
}
return default(T);
}
}
internal static class ValueParsing
{
private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;
public static bool TryParseNumber(string text, Type type, out object value)
{
value = null;
if (string.IsNullOrWhiteSpace(text))
{
return false;
}
text = text.Trim();
int result;
if (type == typeof(int))
{
return Wrap(int.TryParse(text, NumberStyles.Integer, Inv, out result), result, out value);
}
long result2;
if (type == typeof(long))
{
return Wrap(long.TryParse(text, NumberStyles.Integer, Inv, out result2), result2, out value);
}
short result3;
if (type == typeof(short))
{
return Wrap(short.TryParse(text, NumberStyles.Integer, Inv, out result3), result3, out value);
}
byte result4;
if (type == typeof(byte))
{
return Wrap(byte.TryParse(text, NumberStyles.Integer, Inv, out result4), result4, out value);
}
sbyte result5;
if (type == typeof(sbyte))
{
return Wrap(sbyte.TryParse(text, NumberStyles.Integer, Inv, out result5), result5, out value);
}
uint result6;
if (type == typeof(uint))
{
return Wrap(uint.TryParse(text, NumberStyles.Integer, Inv, out result6), result6, out value);
}
ushort result7;
if (type == typeof(ushort))
{
return Wrap(ushort.TryParse(text, NumberStyles.Integer, Inv, out result7), result7, out value);
}
ulong result8;
if (type == typeof(ulong))
{
return Wrap(ulong.TryParse(text, NumberStyles.Integer, Inv, out result8), result8, out value);
}
float result9;
if (type == typeof(float))
{
return Wrap(float.TryParse(text, NumberStyles.Float, Inv, out result9) && !float.IsNaN(result9) && !float.IsInfinity(result9), result9, out value);
}
double result10;
if (type == typeof(double))
{
return Wrap(double.TryParse(text, NumberStyles.Float, Inv, out result10) && !double.IsNaN(result10) && !double.IsInfinity(result10), result10, out value);
}
decimal result11;
if (type == typeof(decimal))
{
return Wrap(decimal.TryParse(text, NumberStyles.Number | NumberStyles.AllowExponent, Inv, out result11), result11, out value);
}
return false;
}
private static bool Wrap<T>(bool ok, T parsed, out object value)
{
value = (ok ? ((object)parsed) : null);
return ok;
}
public static bool InRange(object value, object min, object max)
{
IComparable comparable = (IComparable)value;
if (comparable.CompareTo(min) >= 0)
{
return comparable.CompareTo(max) <= 0;
}
return false;
}
public static double SnapInteger(double value)
{
return Math.Round(value, MidpointRounding.AwayFromZero);
}
public static float RoundToStep(float value, float low, float high)
{
double num = Math.Pow(10.0, Math.Floor(Math.Log10(Math.Max(high - low, 1E-06))) - 2.0);
double val = Math.Round((double)value / num) * num;
return (float)Math.Min(high, Math.Max(low, val));
}
public static string Format(object value)
{
object obj;
if (!(value is IFormattable formattable))
{
obj = value?.ToString();
if (obj == null)
{
return "";
}
}
else
{
obj = formattable.ToString(null, Inv);
}
return (string)obj;
}
public static string FormatSlider(float value, bool integer)
{
return value.ToString(integer ? "0" : "0.##", Inv);
}
}
}
namespace ModSettings.Patches
{
[HarmonyPatch(typeof(OptionsUI), "OnEnable")]
internal static class OptionsEnablePatch
{
private static bool _logged;
private static void Postfix(OptionsUI __instance)
{
try
{
ModsTabInstaller.Install(__instance);
}
catch (Exception arg)
{
if (!_logged)
{
_logged = true;
Plugin.Log.LogError((object)$"Couldn't add the Mods tab; Options is unchanged. {arg}");
}
}
}
}
[HarmonyPatch(typeof(OptionsUI), "OnDisable")]
internal static class OptionsDisablePatch
{
private static void Postfix(OptionsUI __instance)
{
try
{
ModsTabInstaller.Closed(__instance);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"Mods tab close failed. {arg}");
}
}
}
[HarmonyPatch(typeof(OptionsUI), "CycleTab")]
internal static class OptionsCycleTabPatch
{
private static bool Prefix()
{
return !KeyRebind.Listening;
}
}
[HarmonyPatch(typeof(MenuScene), "OnNavigationCancel")]
internal static class MenuSceneCancelPatch
{
private static bool Prefix()
{
return !KeyRebind.ConsumesCancel;
}
}
}