Decompiled source of PutMeDown v1.2.0

PutMeDown.dll

Decompiled 3 months 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 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.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
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_0071: 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 IEnumerable<ToggleStringListConfigEntry.SearchOption> GetItemDropSearchOptions()
		{
			ItemDrop val = default(ItemDrop);
			return from item in ObjectDB.m_instance.m_items
				where 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)
				select new ToggleStringListConfigEntry.SearchOption(((Object)item).name, Localization.m_instance.Localize(item.GetComponent<ItemDrop>().m_itemData.m_shared.m_name) + " (" + ((Object)item).name + ")");
		}
	}
	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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			CodeInstruction instruction;
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (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()! (m_autoPickup)").CopyInstruction(out instruction)
				.Advance(2)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
				{
					instruction,
					Transpilers.EmitDelegate<Func<bool, ItemDrop, bool>>((Func<bool, ItemDrop, bool>)AutoPickupDelegate)
				})
				.InstructionEnumeration();
		}

		private static CodeMatcher CopyInstruction(this CodeMatcher matcher, out CodeInstruction instruction)
		{
			instruction = matcher.Instruction;
			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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdateHover", (Type[])null, (Type[])null), (string)null)
			}).ThrowIfInvalid("Could not patch Player.Update()! (UpdateHover)").Advance(2)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Ldloc_1, (object)null),
					Transpilers.EmitDelegate<Action<bool>>((Action<bool>)UpdateHoverPostDelegate)
				})
				.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.2.0")]
	public sealed class PutMeDown : BaseUnityPlugin
	{
		public const string PluginGuid = "redseiko.valheim.putmedown";

		public const string PluginName = "PutMeDown";

		public const string PluginVersion = "1.2.0";

		private static ManualLogSource _logger;

		private Harmony _harmony;

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

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		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_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				if (_value != value)
				{
					_value = value;
					_currentOptions.Clear();
					if (!string.IsNullOrEmpty(value))
					{
						if (_options == null)
						{
							_options = new List<SearchOption>(_searchOptionsFunc());
						}
						_currentOptions.AddRange(_options.Where((SearchOption option) => option.DisplayValue.IndexOf(value, StringComparison.InvariantCultureIgnoreCase) >= 0 || option.OptionValue.StartsWith(value, StringComparison.InvariantCultureIgnoreCase)));
					}
					_scrollPosition = Vector2.zero;
				}
				if (string.IsNullOrEmpty(_value))
				{
					return string.Empty;
				}
				return DrawCurrentOptions();
			}

			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 static readonly char[] _valueSeparator = new char[1] { ',' };

		private static readonly char[] _toggleSeperator = new char[1] { '=' };

		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, Drawer, browsable: true, hideDefaultButton: false, hideSettingName: false);
			BaseConfigEntry.SettingChanged += OnBaseSettingChanged;
			if (autoCompleteFunc != null)
			{
				_autoCompleteLabel = new AutoCompleteBox(autoCompleteFunc);
			}
		}

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

		public string[] ToggledStringValues()
		{
			_valuesCache.Clear();
			string[] array = BaseConfigEntry.Value.Split(_valueSeparator, StringSplitOptions.RemoveEmptyEntries);
			int i = 0;
			for (int num = array.Length; i < num; i++)
			{
				string[] array2 = array[i].Split(_toggleSeperator, 2, StringSplitOptions.RemoveEmptyEntries);
				if (array2.Length >= 2 && array2[1] == "1")
				{
					_valuesCache.Add(array2[0]);
				}
			}
			return _valuesCache.ToArray();
		}

		public void Drawer(ConfigEntryBase configEntry)
		{
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			_valuesCache.Clear();
			_valuesCache.AddRange(configEntry.BoxedValue.ToString().Split(_valueSeparator, StringSplitOptions.RemoveEmptyEntries));
			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 num = -1;
			int i = 0;
			for (int count = _valuesCache.Count; i < count; i++)
			{
				string[] array = _valuesCache[i].Split(_toggleSeperator, 2, StringSplitOptions.RemoveEmptyEntries);
				bool flag4 = array.Length >= 2 && array[1] == "1";
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				bool flag5 = GUILayout.Toggle(flag4, array[0], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.MinWidth(40f),
					GUILayout.ExpandWidth(false)
				}))
				{
					num = i;
				}
				GUILayout.EndHorizontal();
				if (flag)
				{
					flag5 = true;
				}
				else if (flag2)
				{
					flag5 = false;
				}
				if (flag5 != flag4)
				{
					flag3 = true;
					_valuesCache[i] = array[0] + (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 text = _autoCompleteLabel.DrawBox(_valueText);
				if (!string.IsNullOrEmpty(text))
				{
					_valuesCache.Add(text + "=1");
					flag3 = true;
				}
			}
			GUILayout.EndVertical();
			if (num >= 0)
			{
				_valuesCache.RemoveAt(num);
				flag3 = true;
			}
			if (flag3)
			{
				configEntry.BoxedValue = string.Join(",", _valuesCache);
			}
		}
	}
	public static class ConfigFileExtensions
	{
		internal sealed class ConfigurationManagerAttributes
		{
			public Action<ConfigEntryBase> CustomDrawer;

			public bool? Browsable;

			public bool? HideDefaultButton;

			public int? Order;
		}

		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)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			return config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = GetSettingOrder(section)
				}
			}));
		}

		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)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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,
					Order = GetSettingOrder(section)
				}
			}));
		}

		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>)((SettingChangedEventArgs)eventArgs).ChangedSetting.BoxedValue);
			};
		}
	}
	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;
		}
	}
}