Decompiled source of PutMeDown v1.3.0

PutMeDown.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ComfyLib;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PutMeDown")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PutMeDown")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("287bf250-ae87-4283-867b-9c9351e408fc")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.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 PutMeDown
{
	public static class PluginConfig
	{
		private static readonly List<ToggleStringListConfigEntry> _itemsToIgnoreConfigs = new List<ToggleStringListConfigEntry>();

		private static int _itemsToIgnoreConfigIndex = -1;

		private static ToggleStringListConfigEntry _itemsToIgnoreConfig = null;

		public static ConfigEntry<bool> IsModEnabled { get; private set; }

		public static ToggleStringListConfigEntry ItemsToIgnore { get; private set; }

		public static ConfigEntry<KeyboardShortcut> ItemsToIgnoreCycleShortcut { get; private set; }

		public static ToggleStringListConfigEntry ItemsToIgnoreAlt1 { get; private set; }

		public static ToggleStringListConfigEntry ItemsToIgnoreAlt2 { get; private set; }

		[ComfyConfig]
		public static void BindConfig(ConfigFile config)
		{
			IsModEnabled = config.BindInOrder("_Global", "isModEnabled", defaultValue: true, "Globally enable or disable this mod.");
		}

		[ComfyConfig(LateBind = true)]
		public static void BindAutoPickupConfig(ConfigFile config)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			_itemsToIgnoreConfigs.Clear();
			_itemsToIgnoreConfigIndex = -1;
			ItemsToIgnore = new ToggleStringListConfigEntry(config, "AutoPickup", "itemsToIgnore", "Wood=0,Stone=0", "Items to ignore for auto-pickup behaviour (normal config).", GetItemDropSearchOptions);
			_itemsToIgnoreConfigs.Add(ItemsToIgnore);
			ItemsToIgnore.SettingChanged += OnItemsToIgnoreChanged;
			ItemsToIgnoreCycleShortcut = config.BindInOrder<KeyboardShortcut>("AutoPickup.Alt", "itemsToIgnoreCycleShortcut", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Shortcut to cycle through ItemsToIgnore normal and alternate configs.");
			ItemsToIgnoreAlt1 = new ToggleStringListConfigEntry(config, "AutoPickup.Alt", "itemsToIgnoreAlt1", "Wood=0,Stone=0", "Items to ignore for auto-pickup behaviour (alternate config 1).", GetItemDropSearchOptions);
			_itemsToIgnoreConfigs.Add(ItemsToIgnoreAlt1);
			ItemsToIgnoreAlt1.SettingChanged += OnItemsToIgnoreChanged;
			ItemsToIgnoreAlt2 = new ToggleStringListConfigEntry(config, "AutoPickup.Alt", "itemsToIgnoreAlt2", "Wood=0,Stone=0", "Items to ignore for auto-pickup behaviour (alternate config 2).", GetItemDropSearchOptions);
			_itemsToIgnoreConfigs.Add(ItemsToIgnoreAlt2);
			ItemsToIgnoreAlt2.SettingChanged += OnItemsToIgnoreChanged;
			CycleItemsToIgnoreConfig();
		}

		public static void CycleItemsToIgnoreConfig()
		{
			_itemsToIgnoreConfigIndex++;
			if (_itemsToIgnoreConfigIndex < 0 || _itemsToIgnoreConfigIndex >= _itemsToIgnoreConfigs.Count)
			{
				_itemsToIgnoreConfigIndex = 0;
			}
			_itemsToIgnoreConfig = _itemsToIgnoreConfigs[_itemsToIgnoreConfigIndex];
			AutoPickupController.SetItemsToIgnore(_itemsToIgnoreConfig.ToggledStringValues());
		}

		private static void OnItemsToIgnoreChanged(object sender, IEnumerable<string> itemsToIgnore)
		{
			if (sender == _itemsToIgnoreConfig)
			{
				AutoPickupController.SetItemsToIgnore(itemsToIgnore);
			}
		}

		public static List<ToggleStringListConfigEntry.SearchOption> GetItemDropSearchOptions()
		{
			List<ToggleStringListConfigEntry.SearchOption> list = new List<ToggleStringListConfigEntry.SearchOption>();
			ItemDrop val = default(ItemDrop);
			foreach (GameObject item in ObjectDB.m_instance.m_items)
			{
				if (item.TryGetComponent<ItemDrop>(ref val) && val.m_autoPickup && val.m_itemData.m_shared.m_icons.Length != 0 && !string.IsNullOrEmpty(val.m_itemData.m_shared.m_description))
				{
					string text = Localization.m_instance.Localize(val.m_itemData.m_shared.m_name);
					list.Add(new ToggleStringListConfigEntry.SearchOption(((Object)item).name, text + " (" + ((Object)item).name + ")"));
				}
			}
			return list;
		}
	}
	public static class AutoPickupController
	{
		private static readonly HashSet<string> _itemsToIgnore = new HashSet<string>();

		public static void SetItemsToIgnore(IEnumerable<string> itemsToIgnore)
		{
			_itemsToIgnore.Clear();
			_itemsToIgnore.UnionWith(itemsToIgnore);
			PutMeDown.LogInfo(string.Format("Ignoring {0} items: {1}", _itemsToIgnore.Count, string.Join(", ", _itemsToIgnore)));
		}

		public static bool ShouldIgnoreItem(ItemDrop itemDrop)
		{
			return _itemsToIgnore.Contains(((Object)itemDrop.m_itemData.m_dropPrefab).name);
		}
	}
	[HarmonyPatch(typeof(Player))]
	internal static class PlayerPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch("AutoPickup")]
		private static IEnumerable<CodeInstruction> AutoPickupTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: 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_0026: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			CodeInstruction instruction;
			return new CodeMatcher(instructions, (ILGenerator)null).Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(ItemDrop), "m_autoPickup"), (string)null)
			}).ThrowIfInvalid("Could not patch Player.AutoPickup()! (auto-pickup)")
				.CopyInstruction(out instruction)
				.Advance(2)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
				{
					instruction,
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlayerPatch), "AutoPickupDelegate", (Type[])null, (Type[])null))
				})
				.InstructionEnumeration();
		}

		private static CodeMatcher CopyInstruction(this CodeMatcher matcher, out CodeInstruction instruction)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			instruction = new CodeInstruction(matcher.Opcode, matcher.Operand);
			return matcher;
		}

		private static bool AutoPickupDelegate(bool autoPickup, ItemDrop itemDrop)
		{
			if (autoPickup && PluginConfig.IsModEnabled.Value && AutoPickupController.ShouldIgnoreItem(itemDrop))
			{
				return false;
			}
			return autoPickup;
		}

		[HarmonyTranspiler]
		[HarmonyPatch("Update")]
		private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdateHover", (Type[])null, (Type[])null), (string)null)
			}).ThrowIfInvalid("Could not patch Player.Update()! (update-hover)")
				.Advance(1)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Ldloc_1, (object)null),
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlayerPatch), "UpdateHoverPostDelegate", (Type[])null, (Type[])null))
				})
				.InstructionEnumeration();
		}

		private static void UpdateHoverPostDelegate(bool takeInput)
		{
			//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)
			if (takeInput && PluginConfig.IsModEnabled.Value)
			{
				KeyboardShortcut value = PluginConfig.ItemsToIgnoreCycleShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					PluginConfig.CycleItemsToIgnoreConfig();
				}
			}
		}
	}
	[BepInPlugin("redseiko.valheim.putmedown", "PutMeDown", "1.3.0")]
	public sealed class PutMeDown : BaseUnityPlugin
	{
		public const string PluginGuid = "redseiko.valheim.putmedown";

		public const string PluginName = "PutMeDown";

		public const string PluginVersion = "1.3.0";

		private static ManualLogSource _logger;

		private void Awake()
		{
			_logger = ((BaseUnityPlugin)this).Logger;
			ComfyConfigUtils.BindConfig(((BaseUnityPlugin)this).Config);
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "redseiko.valheim.putmedown");
		}

		public static void LogInfo(object obj)
		{
			_logger.LogInfo((object)$"[{DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo)}] {obj}");
			Chat.m_instance.AddMessage(obj);
		}
	}
}
namespace ComfyLib
{
	[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
	public sealed class ComfyConfigAttribute : Attribute
	{
		public bool LateBind { get; set; }
	}
	public static class ComfyConfigUtils
	{
		[HarmonyPatch]
		private static class ComfyConfigBinder
		{
			private static readonly Queue<Action> _lateBindQueue = new Queue<Action>();

			private static bool _startupPatched = false;

			public static void Bind(ConfigFile config, MethodInfo method, ComfyConfigAttribute attribute)
			{
				if (!attribute.LateBind || _startupPatched)
				{
					method.Invoke(null, new object[1] { config });
					return;
				}
				_lateBindQueue.Enqueue(delegate
				{
					method.Invoke(null, new object[1] { config });
				});
			}

			[HarmonyPatch(typeof(FejdStartup), "Start")]
			private static void Postfix()
			{
				while (_lateBindQueue.Count > 0)
				{
					_lateBindQueue.Dequeue()?.Invoke();
				}
				_startupPatched = true;
			}
		}

		public static void BindConfig(ConfigFile config)
		{
			BindConfigs(config, Assembly.GetExecutingAssembly());
		}

		private static void BindConfigs(ConfigFile config, Assembly assembly)
		{
			foreach (var (method, attribute) in GetBindConfigMethods(assembly))
			{
				ComfyConfigBinder.Bind(config, method, attribute);
			}
		}

		private static IEnumerable<(MethodInfo, ComfyConfigAttribute)> GetBindConfigMethods(Assembly assembly)
		{
			return assembly.GetTypes().SelectMany((Type type) => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)).SelectMany((MethodInfo method) => GetBindConfigMethod(method));
		}

		private static IEnumerable<(MethodInfo, ComfyConfigAttribute)> GetBindConfigMethod(MethodInfo method)
		{
			ComfyConfigAttribute customAttribute = method.GetCustomAttribute<ComfyConfigAttribute>(inherit: false);
			if (customAttribute != null)
			{
				ParameterInfo[] parameters = method.GetParameters();
				if (parameters.Length == 1 && parameters[0].ParameterType == typeof(ConfigFile))
				{
					yield return (method, customAttribute);
				}
			}
		}
	}
	public sealed class ToggleStringListConfigEntry
	{
		public sealed class SearchOption
		{
			public string OptionValue = string.Empty;

			public string DisplayValue = string.Empty;

			public SearchOption(string optionValue)
				: this(optionValue, optionValue)
			{
			}

			public SearchOption(string optionValue, string displayValue)
			{
				OptionValue = optionValue;
				DisplayValue = displayValue;
			}
		}

		public sealed class AutoCompleteBox
		{
			private readonly Func<IEnumerable<SearchOption>> _searchOptionsFunc;

			private List<SearchOption> _options;

			private readonly List<SearchOption> _currentOptions;

			private string _value;

			private Vector2 _scrollPosition;

			public AutoCompleteBox(Func<IEnumerable<SearchOption>> searchOptionsFunc)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				_searchOptionsFunc = searchOptionsFunc;
				_options = null;
				_currentOptions = new List<SearchOption>();
				_value = string.Empty;
				_scrollPosition = Vector2.zero;
			}

			public string DrawBox(string value)
			{
				//IL_0022: 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 (_value != value)
				{
					_value = value;
					FilterOptions(_value);
					_scrollPosition = Vector2.zero;
				}
				if (string.IsNullOrEmpty(_value))
				{
					return string.Empty;
				}
				return DrawCurrentOptions();
			}

			private void FilterOptions(string query)
			{
				_currentOptions.Clear();
				if (string.IsNullOrEmpty(query))
				{
					return;
				}
				if (_options == null)
				{
					_options = _searchOptionsFunc().ToList();
				}
				foreach (SearchOption option in _options)
				{
					if (option.DisplayValue.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0 || option.OptionValue.StartsWith(query, StringComparison.OrdinalIgnoreCase))
					{
						_currentOptions.Add(option);
					}
				}
			}

			private string DrawCurrentOptions()
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				_scrollPosition = GUILayout.BeginScrollView(_scrollPosition, GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(true),
					GUILayout.Height(120f)
				});
				string result = string.Empty;
				foreach (SearchOption currentOption in _currentOptions)
				{
					if (GUILayout.Button(currentOption.DisplayValue, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(40f) }))
					{
						result = currentOption.OptionValue;
					}
				}
				GUILayout.EndScrollView();
				return result;
			}
		}

		public readonly ConfigEntry<string> BaseConfigEntry;

		private readonly AutoCompleteBox _autoCompleteLabel;

		private readonly List<string> _valuesCache = new List<string>();

		private string _valueText = string.Empty;

		public event EventHandler<string[]> SettingChanged;

		public ToggleStringListConfigEntry(ConfigFile config, string section, string key, string defaultValue, string description, Func<IEnumerable<SearchOption>> autoCompleteFunc = null)
		{
			BaseConfigEntry = config.BindInOrder(section, key, defaultValue, description, (Action<ConfigEntryBase>)Drawer, browsable: true, hideDefaultButton: false, hideSettingName: false, isAdvanced: false, readOnly: false);
			BaseConfigEntry.SettingChanged += OnBaseSettingChanged;
			if (autoCompleteFunc != null)
			{
				_autoCompleteLabel = new AutoCompleteBox(autoCompleteFunc);
			}
		}

		private void OnBaseSettingChanged(object sender, EventArgs eventArgs)
		{
			this.SettingChanged?.Invoke(this, ToggledStringValues());
		}

		private static bool IsToggledOn(ReadOnlySpan<char> value)
		{
			if (value.Length == 1)
			{
				return value[0] == '1';
			}
			return false;
		}

		public string[] ToggledStringValues()
		{
			_valuesCache.Clear();
			ReadOnlySpan<char> readOnlySpan = BaseConfigEntry.Value.AsSpan();
			while (!readOnlySpan.IsEmpty)
			{
				int num = readOnlySpan.IndexOf(',');
				ReadOnlySpan<char> span = ((num >= 0) ? readOnlySpan.Slice(0, num) : readOnlySpan);
				ReadOnlySpan<char> obj;
				if (num < 0)
				{
					obj = default(ReadOnlySpan<char>);
				}
				else
				{
					ref ReadOnlySpan<char> reference = ref readOnlySpan;
					int num2 = num + 1;
					obj = reference.Slice(num2, reference.Length - num2);
				}
				readOnlySpan = obj;
				if (span.IsEmpty)
				{
					continue;
				}
				int num3 = span.IndexOf('=');
				if (num3 > 0)
				{
					ref ReadOnlySpan<char> reference = ref span;
					int num2 = num3 + 1;
					if (IsToggledOn(reference.Slice(num2, reference.Length - num2)))
					{
						_valuesCache.Add(span.Slice(0, num3).ToString());
					}
				}
			}
			return _valuesCache.ToArray();
		}

		public void Drawer(ConfigEntryBase configEntry)
		{
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			_valuesCache.Clear();
			ReadOnlySpan<char> readOnlySpan = BaseConfigEntry.Value.AsSpan();
			while (!readOnlySpan.IsEmpty)
			{
				int num = readOnlySpan.IndexOf(',');
				ReadOnlySpan<char> readOnlySpan2 = ((num >= 0) ? readOnlySpan.Slice(0, num) : readOnlySpan);
				ReadOnlySpan<char> obj;
				if (num < 0)
				{
					obj = default(ReadOnlySpan<char>);
				}
				else
				{
					ref ReadOnlySpan<char> reference = ref readOnlySpan;
					int num2 = num + 1;
					obj = reference.Slice(num2, reference.Length - num2);
				}
				readOnlySpan = obj;
				if (!readOnlySpan2.IsEmpty)
				{
					_valuesCache.Add(readOnlySpan2.ToString());
				}
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag = GUILayout.Button("Toggle On", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			bool flag2 = GUILayout.Button("Toggle Off", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.EndHorizontal();
			bool flag3 = false;
			int num3 = -1;
			int i = 0;
			for (int count = _valuesCache.Count; i < count; i++)
			{
				ReadOnlySpan<char> span = _valuesCache[i].AsSpan();
				int num4 = span.IndexOf('=');
				int num5;
				if (num4 > 0)
				{
					ref ReadOnlySpan<char> reference = ref span;
					int num2 = num4 + 1;
					num5 = (IsToggledOn(reference.Slice(num2, reference.Length - num2)) ? 1 : 0);
				}
				else
				{
					num5 = 0;
				}
				bool flag4 = (byte)num5 != 0;
				string text = ((num4 > 0) ? span.Slice(0, num4).ToString() : _valuesCache[i]);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				bool flag5 = GUILayout.Toggle(flag4, text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.MinWidth(40f),
					GUILayout.ExpandWidth(false)
				}))
				{
					num3 = i;
				}
				GUILayout.EndHorizontal();
				if (flag)
				{
					flag5 = true;
				}
				else if (flag2)
				{
					flag5 = false;
				}
				if (flag5 != flag4)
				{
					flag3 = true;
					_valuesCache[i] = text + (flag5 ? "=1" : "=0");
				}
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			_valueText = GUILayout.TextField(_valueText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.Space(3f);
			if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.MinWidth(40f),
				GUILayout.ExpandWidth(false)
			}) && !string.IsNullOrWhiteSpace(_valueText) && _valueText.IndexOf('=') < 0)
			{
				_valuesCache.Add(_valueText + "=1");
				_valueText = string.Empty;
				flag3 = true;
			}
			GUILayout.EndHorizontal();
			if (_autoCompleteLabel != null)
			{
				string text2 = _autoCompleteLabel.DrawBox(_valueText);
				if (!string.IsNullOrEmpty(text2))
				{
					_valuesCache.Add(text2 + "=1");
					flag3 = true;
				}
			}
			GUILayout.EndVertical();
			if (num3 >= 0)
			{
				_valuesCache.RemoveAt(num3);
				flag3 = true;
			}
			if (flag3)
			{
				BaseConfigEntry.Value = string.Join(",", _valuesCache);
			}
		}
	}
	public static class ConfigFileExtensions
	{
		internal sealed class ConfigurationManagerAttributes
		{
			public Action<ConfigEntryBase> CustomDrawer;

			public bool? Browsable;

			public bool? HideDefaultButton;

			public bool? HideSettingName;

			public bool? IsAdvanced;

			public int? Order;

			public bool? ReadOnly;
		}

		private static readonly Dictionary<string, int> _sectionToSettingOrder = new Dictionary<string, int>();

		private static int GetSettingOrder(string section)
		{
			if (!_sectionToSettingOrder.TryGetValue(section, out var value))
			{
				value = 0;
			}
			_sectionToSettingOrder[section] = value - 1;
			return value;
		}

		public static ConfigEntry<T> BindInOrder<T>(this ConfigFile config, string section, string key, T defaultValue, string description, AcceptableValueBase acceptableValues, bool browsable = true, bool hideDefaultButton = false, bool hideSettingName = false, bool isAdvanced = false, bool readOnly = false)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = browsable,
					CustomDrawer = null,
					HideDefaultButton = hideDefaultButton,
					HideSettingName = hideSettingName,
					IsAdvanced = isAdvanced,
					Order = GetSettingOrder(section),
					ReadOnly = readOnly
				}
			}));
		}

		public static ConfigEntry<T> BindInOrder<T>(this ConfigFile config, string section, string key, T defaultValue, string description, Action<ConfigEntryBase> customDrawer = null, bool browsable = true, bool hideDefaultButton = false, bool hideSettingName = false, bool isAdvanced = false, bool readOnly = false)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = browsable,
					CustomDrawer = customDrawer,
					HideDefaultButton = hideDefaultButton,
					HideSettingName = hideSettingName,
					IsAdvanced = isAdvanced,
					Order = GetSettingOrder(section),
					ReadOnly = readOnly
				}
			}));
		}

		public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action settingChangedHandler)
		{
			configEntry.SettingChanged += delegate
			{
				settingChangedHandler();
			};
		}

		public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action<T> settingChangedHandler)
		{
			configEntry.SettingChanged += delegate(object _, EventArgs eventArgs)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				settingChangedHandler((T)((SettingChangedEventArgs)eventArgs).ChangedSetting.BoxedValue);
			};
		}

		public static void OnSettingChanged<T>(this ConfigEntry<T> configEntry, Action<ConfigEntry<T>> settingChangedHandler)
		{
			configEntry.SettingChanged += delegate(object _, EventArgs eventArgs)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				settingChangedHandler((ConfigEntry<T>)(object)((SettingChangedEventArgs)eventArgs).ChangedSetting);
			};
		}
	}
	public static class ChatExtensions
	{
		public static void AddMessage(this Chat chat, object obj)
		{
			if (Object.op_Implicit((Object)(object)chat))
			{
				((Terminal)chat).AddString($"{obj}");
				chat.m_hideTimer = 0f;
			}
		}
	}
	public static class ObjectExtensions
	{
		public static T Ref<T>(this T unityObject) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)unityObject))
			{
				return default(T);
			}
			return unityObject;
		}
	}
}