Decompiled source of Automatics v1.5.1

plugins/Automatics.dll

Decompiled 7 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using Automatics.AutomaticDoor;
using Automatics.AutomaticMapping;
using Automatics.AutomaticProcessing;
using Automatics.ConsoleCommands;
using Automatics.Valheim;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using LitJson;
using ModUtils;
using NDesk.Options;
using UnityEngine;

[assembly: Guid("1821CB9A-56A9-4013-B268-86F0704773CF")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright © 2022-2023")]
[assembly: AssemblyProduct("Automatics")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("Automatics")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyFileVersion("1.5.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.5.1.0")]
namespace ModUtils
{
	public class Configuration
	{
		private const int DefaultOrder = 4096;

		private readonly ConfigFile _config;

		private readonly L10N _localization;

		private Logger _logger;

		private string Section { get; set; } = "general";


		private int Order { get; set; } = 4096;


		static Configuration()
		{
			//IL_001b: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			if (!TomlTypeConverter.CanConvert(typeof(StringList)))
			{
				TomlTypeConverter.AddConverter(typeof(StringList), new TypeConverter
				{
					ConvertToObject = (string str, Type type) => (!string.IsNullOrEmpty(str)) ? new StringList(Csv.ParseLine(str)) : new StringList(),
					ConvertToString = delegate(object obj, Type type)
					{
						StringList source = (StringList)obj;
						return string.Join(", ", source.Select(Csv.Escape));
					}
				});
			}
			if (!TomlTypeConverter.CanConvert(typeof(KeyboardShortcut)))
			{
				TomlTypeConverter.AddConverter(typeof(KeyboardShortcut), new TypeConverter
				{
					ConvertToObject = (string str, Type type) => KeyboardShortcut.Deserialize(str),
					ConvertToString = delegate(object obj, Type type)
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						KeyboardShortcut val = (KeyboardShortcut)obj;
						return ((KeyboardShortcut)(ref val)).Serialize();
					}
				});
			}
		}

		public Configuration(ConfigFile config, L10N localization)
		{
			_config = config;
			_localization = localization;
		}

		private void LogSection(string section)
		{
			_logger?.Debug("[CONFIG] === " + GetSection(section) + " / [" + section + "]");
		}

		private void LogConfigEntry<T>(ConfigEntry<T> entry, ConfigurationManagerAttributes attributes)
		{
			_logger?.Debug("[CONFIG] ==== " + attributes.DispName + " / [" + ((ConfigEntryBase)entry).Definition.Key + "]");
			_logger?.Debug("[CONFIG] " + ((ConfigEntryBase)entry).Description.Description);
			_logger?.Debug("[CONFIG] ");
			Type type = typeof(T);
			object defaultValue = ((ConfigEntryBase)entry).DefaultValue;
			if (attributes.ObjToStr != null)
			{
				_logger?.Debug("[CONFIG] - Default value: " + attributes.ObjToStr(defaultValue));
			}
			else if (TomlTypeConverter.CanConvert(type))
			{
				_logger?.Debug("[CONFIG] - Default value: " + TomlTypeConverter.ConvertToString(defaultValue, type));
			}
			else
			{
				_logger?.Debug($"[CONFIG] - Default value: {defaultValue}");
			}
			AcceptableValueBase acceptableValues = ((ConfigEntryBase)entry).Description.AcceptableValues;
			if (acceptableValues != null)
			{
				string[] array = acceptableValues.ToDescriptionString().Split(new char[1] { '\n' });
				foreach (string text in array)
				{
					_logger?.Debug("[CONFIG] - " + text);
				}
			}
			else if (type.IsEnum)
			{
				List<string> list = (from x in Enum.GetValues(type).OfType<T>()
					select Enum.GetName(type, x)).ToList();
				_logger?.Debug("[CONFIG] - Acceptable values: " + string.Join(", ", list));
				if (type.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any())
				{
					IEnumerable<string> values = list.Where((string x) => !string.Equals(x, "none", StringComparison.OrdinalIgnoreCase) && !string.Equals(x, "all", StringComparison.OrdinalIgnoreCase)).Take(2);
					_logger?.Debug("[CONFIG] - Multiple values can be set at the same time by separating them with , (e.g. " + string.Join(", ", values) + ")");
				}
			}
			_logger?.Debug("[CONFIG] ");
		}

		public void SetDebugLogger(Logger logger)
		{
			_logger = logger;
		}

		public void ChangeSection(string section, int initialOrder = 4096)
		{
			Section = section;
			Order = initialOrder;
			if (_logger != null)
			{
				LogSection(Section);
			}
		}

		private ConfigEntry<T> Bind<T>(string section, int order, string key, T defaultValue, AcceptableValueBase acceptableValue = null, Action<ConfigurationManagerAttributes> initializer = null)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Category = GetSection(section),
				Order = order,
				DispName = GetName(section, key),
				CustomDrawer = ConfigurationCustomDrawer.Get(typeof(T), acceptableValue)
			};
			initializer?.Invoke(configurationManagerAttributes);
			string text = (string.IsNullOrEmpty(configurationManagerAttributes.Description) ? GetDescription(section, key) : configurationManagerAttributes.Description);
			ConfigEntry<T> val = _config.Bind<T>(section, key, defaultValue, new ConfigDescription(text, acceptableValue, new object[1] { configurationManagerAttributes }));
			if (_logger != null)
			{
				LogConfigEntry<T>(val, configurationManagerAttributes);
			}
			return val;
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, AcceptableValueBase acceptableValue = null, Action<ConfigurationManagerAttributes> initializer = null)
		{
			return Bind(section, Order--, key, defaultValue, acceptableValue, initializer);
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, (T, T) acceptableValue, Action<ConfigurationManagerAttributes> initializer = null) where T : IComparable
		{
			var (val, val2) = acceptableValue;
			return Bind(section, key, defaultValue, (AcceptableValueBase)(object)new AcceptableValueRange<T>(val, val2), initializer);
		}

		public ConfigEntry<T> Bind<T>(string key, T defaultValue, AcceptableValueBase acceptableValue = null, Action<ConfigurationManagerAttributes> initializer = null)
		{
			return Bind(Section, key, defaultValue, acceptableValue, initializer);
		}

		public ConfigEntry<T> Bind<T>(string key, T defaultValue, (T, T) acceptableValue, Action<ConfigurationManagerAttributes> initializer = null) where T : IComparable
		{
			return Bind(Section, key, defaultValue, acceptableValue, initializer);
		}

		private string GetSection(string section)
		{
			return _localization.Translate("@config_" + section + "_section");
		}

		private string GetName(string section, string key)
		{
			return _localization.Translate("@config_" + section + "_" + key + "_name");
		}

		private string GetDescription(string section, string key)
		{
			return _localization.Translate("@config_" + section + "_" + key + "_description");
		}
	}
	public class StringList : ICollection<string>, IEnumerable<string>, IEnumerable
	{
		private readonly HashSet<string> _values;

		public int Count => _values.Count;

		public bool IsReadOnly => false;

		public StringList()
		{
			_values = new HashSet<string>();
		}

		public StringList(IEnumerable<string> collection)
		{
			_values = new HashSet<string>(collection);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public IEnumerator<string> GetEnumerator()
		{
			return _values.GetEnumerator();
		}

		public void Add(string item)
		{
			_values.Add(item);
		}

		public void Clear()
		{
			_values.Clear();
		}

		public bool Contains(string item)
		{
			return _values.Contains(item);
		}

		public void CopyTo(string[] array, int arrayIndex)
		{
			_values.CopyTo(array, arrayIndex);
		}

		public bool Remove(string item)
		{
			return _values.Remove(item);
		}

		public bool TryAdd(string item)
		{
			return _values.Add(item);
		}
	}
	public class LocalizedDescriptionAttribute : DescriptionAttribute
	{
		private readonly string _prefix;

		private readonly string _key;

		public override string Description => L10N.Translate(_prefix, _key);

		public LocalizedDescriptionAttribute(string prefix, string key)
			: base(key)
		{
			_prefix = prefix;
			_key = key;
		}

		public LocalizedDescriptionAttribute(string key)
			: this("", key)
		{
		}
	}
	public class AcceptableValueEnum<T> : AcceptableValueBase where T : Enum
	{
		private readonly bool _isFlags;

		private readonly IList<T> _values;

		public AcceptableValueEnum(params T[] values)
			: base(typeof(T))
		{
			_isFlags = ((AcceptableValueBase)this).ValueType.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any();
			_values = MakeValues(((AcceptableValueBase)this).ValueType, (IReadOnlyCollection<T>)(object)values, _isFlags);
		}

		private static IList<T> MakeValues(Type type, IReadOnlyCollection<T> values, bool isFlags)
		{
			object collection;
			if (values.Count != 0)
			{
				collection = values;
			}
			else
			{
				collection = Enum.GetValues(type).OfType<T>();
			}
			List<T> list = new List<T>((IEnumerable<T>)collection);
			if (!isFlags)
			{
				return list;
			}
			HashSet<long> hashSet = new HashSet<long>();
			foreach (long item in list.Select((T @enum) => Convert.ToInt64(@enum)))
			{
				long[] array = hashSet.ToArray();
				foreach (long num in array)
				{
					hashSet.Add(num | item);
				}
				hashSet.Add(item);
			}
			return hashSet.Select((long x) => Enum.ToObject(type, x)).Cast<T>().ToList();
		}

		public override object Clamp(object value)
		{
			if (!((AcceptableValueBase)this).IsValid(value))
			{
				return _values[0];
			}
			return value;
		}

		public override bool IsValid(object value)
		{
			if (value is T item)
			{
				return _values.Contains(item);
			}
			if (!(value is IConvertible))
			{
				return false;
			}
			long @long = Convert.ToInt64(value);
			return _values.Any((T x) => Convert.ToInt64(x) == @long);
		}

		public override string ToDescriptionString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			Type type = typeof(T);
			List<string> list = (from x in _values
				where Enum.IsDefined(type, x)
				select Enum.GetName(type, x)).ToList();
			stringBuilder.Append("# Acceptable values: ").Append(string.Join(", ", list));
			if (!_isFlags)
			{
				return stringBuilder.ToString();
			}
			List<string> list2 = list.Where((string x) => !string.Equals(x, "none", StringComparison.OrdinalIgnoreCase) && !string.Equals(x, "all", StringComparison.OrdinalIgnoreCase)).Take(2).ToList();
			if (list2.Count == 2)
			{
				stringBuilder.Append('\n').Append("# Multiple values can be set at the same time by separating them with , (e.g. ").Append(string.Join(", ", list2))
					.Append(")");
			}
			return stringBuilder.ToString();
		}
	}
	public static class ConfigurationCustomDrawer
	{
		public delegate bool IsMatchConfig(Type type, AcceptableValueBase acceptableValue);

		public delegate Action<ConfigEntryBase> CustomDrawerSupplier();

		private const string L10NPrefix = "mod_utils";

		private const string EnabledKey = "@config_button_enabled";

		private const string DisabledKey = "@config_button_disabled";

		private const string AddKey = "@config_button_add";

		private const string RemoveKey = "@config_button_remove";

		private static readonly Dictionary<IsMatchConfig, CustomDrawerSupplier> CustomDrawers;

		static ConfigurationCustomDrawer()
		{
			Dictionary<string, string> field = Reflections.GetField<Dictionary<string, string>>(Localization.instance, "m_translations");
			string translationKey = L10N.GetTranslationKey("mod_utils", "@config_button_enabled");
			if (!field.ContainsKey(translationKey))
			{
				field.Add(translationKey, "Enabled");
			}
			translationKey = L10N.GetTranslationKey("mod_utils", "@config_button_disabled");
			if (!field.ContainsKey(translationKey))
			{
				field.Add(translationKey, "Disabled");
			}
			translationKey = L10N.GetTranslationKey("mod_utils", "@config_button_add");
			if (!field.ContainsKey(translationKey))
			{
				field.Add(translationKey, "Add");
			}
			translationKey = L10N.GetTranslationKey("mod_utils", "@config_button_remove");
			if (!field.ContainsKey(translationKey))
			{
				field.Add(translationKey, "Remove");
			}
			CustomDrawers = new Dictionary<IsMatchConfig, CustomDrawerSupplier>
			{
				{
					IsBool,
					() => Bool
				},
				{
					IsFloatWithRange,
					() => FloatSlider
				},
				{ IsStringList, StringList },
				{
					IsFlagsEnum,
					() => Flags
				}
			};
		}

		private static bool IsBool(Type type, AcceptableValueBase acceptableValue)
		{
			return type == typeof(bool);
		}

		private static bool IsFloatWithRange(Type type, AcceptableValueBase acceptableValue)
		{
			if (type == typeof(float))
			{
				return acceptableValue is AcceptableValueRange<float>;
			}
			return false;
		}

		private static bool IsStringList(Type type, AcceptableValueBase acceptableValue)
		{
			if (type == typeof(float))
			{
				return acceptableValue is AcceptableValueRange<float>;
			}
			return false;
		}

		private static bool IsFlagsEnum(Type type, AcceptableValueBase acceptableValue)
		{
			if (type.IsEnum)
			{
				return type.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any();
			}
			return false;
		}

		public static void Bool(ConfigEntryBase entry)
		{
			bool flag = (bool)entry.BoxedValue;
			string text = L10N.Translate("mod_utils", flag ? "@config_button_enabled" : "@config_button_disabled");
			bool flag2 = GUILayout.Toggle(flag, text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (flag2 != flag)
			{
				entry.BoxedValue = flag2;
			}
		}

		public static void FloatSlider(ConfigEntryBase entry)
		{
			AcceptableValueRange<float> val = (AcceptableValueRange<float>)(object)entry.Description.AcceptableValues;
			float num = (float)entry.BoxedValue;
			float minValue = val.MinValue;
			float maxValue = val.MaxValue;
			float num2 = GUILayout.HorizontalSlider(num, minValue, maxValue, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			num2 = Mathf.Floor(num2 * 100f) / 100f;
			if (Math.Abs(num2 - num) > Mathf.Abs(maxValue - minValue) / 1000f)
			{
				entry.BoxedValue = num2;
			}
			string text = num.ToString("0.00", CultureInfo.InvariantCulture);
			string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (text2 == text)
			{
				return;
			}
			try
			{
				num2 = (float)Convert.ToDouble(text2, CultureInfo.InvariantCulture);
				object boxedValue = Convert.ChangeType(((AcceptableValueBase)val).Clamp((object)num2), entry.SettingType, CultureInfo.InvariantCulture);
				entry.BoxedValue = boxedValue;
			}
			catch (FormatException)
			{
			}
		}

		private static Action<ConfigEntryBase> StringList()
		{
			string inputText = "";
			return delegate(ConfigEntryBase entry)
			{
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: Expected O, but got Unknown
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Expected O, but got Unknown
				//IL_013a: Unknown result type (might be due to invalid IL or missing references)
				int num = Mathf.Min(Screen.width, 650);
				int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115;
				string text = L10N.Translate("mod_utils", "@config_button_add");
				string text2 = L10N.Translate("mod_utils", "@config_button_remove");
				StringList stringList = new StringList((StringList)entry.BoxedValue);
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) });
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				inputText = GUILayout.TextField(inputText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if (GUILayout.Button(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }) && !string.IsNullOrEmpty(inputText))
				{
					if (stringList.TryAdd(inputText))
					{
						entry.BoxedValue = stringList;
					}
					inputText = "";
				}
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				double num3 = 0.0;
				foreach (string item in stringList.ToList())
				{
					int num4 = Mathf.FloorToInt(GUI.skin.label.CalcSize(new GUIContent(item)).x) + Mathf.FloorToInt(GUI.skin.button.CalcSize(new GUIContent(text2)).x);
					num3 += (double)num4;
					if (num3 > (double)num2)
					{
						GUILayout.EndHorizontal();
						num3 = num4;
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					}
					GUILayout.Label(item, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
					if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }) && stringList.Remove(item))
					{
						entry.BoxedValue = stringList;
					}
				}
				GUILayout.EndHorizontal();
				GUILayout.EndVertical();
				GUILayout.FlexibleSpace();
			};
		}

		public static void Flags(ConfigEntryBase entry)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Min(Screen.width, 650);
			int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115;
			Type settingType = entry.SettingType;
			long num3 = Convert.ToInt64(entry.BoxedValue);
			AcceptableValueBase acceptableValues = entry.Description.AcceptableValues;
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) });
			int num4 = 0;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			foreach (object value2 in Enum.GetValues(settingType))
			{
				if (acceptableValues != null && !acceptableValues.IsValid(value2))
				{
					continue;
				}
				long num5 = Convert.ToInt64(value2);
				if (num5 != 0L)
				{
					string text = GetFlagsLabel(settingType, value2);
					int num6 = Mathf.FloorToInt(GUI.skin.toggle.CalcSize(new GUIContent(text + "_")).x);
					num4 += num6;
					if (num4 > num2)
					{
						GUILayout.EndHorizontal();
						num4 = num6;
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					}
					GUI.changed = false;
					bool flag = GUILayout.Toggle((num3 & num5) == num5, text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
					if (GUI.changed)
					{
						long value = (flag ? (num3 | num5) : (num3 & ~num5));
						entry.BoxedValue = Enum.ToObject(settingType, value);
					}
				}
			}
			GUILayout.EndHorizontal();
			GUI.changed = false;
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			static string GetFlagsLabel(Type type, object @object)
			{
				return (type.GetMember(Enum.GetName(type, @object) ?? "").FirstOrDefault()?.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false).OfType<DescriptionAttribute>().FirstOrDefault())?.Description ?? @object.ToString();
			}
		}

		public static Action<ConfigEntryBase> MultiSelect<T>(Func<IEnumerable<T>> allElementSupplier, Func<T, string> labelGenerator) where T : IComparable<T>
		{
			return delegate(ConfigEntryBase entry)
			{
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0134: Expected O, but got Unknown
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				int num = Mathf.Min(Screen.width, 650);
				int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115;
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) });
				Type settingType = entry.SettingType;
				ConstructorInfo constructor = settingType.GetConstructor(new Type[1] { typeof(IEnumerable<T>) });
				if ((object)constructor == null)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"{settingType} does not define a constructor that takes IEnumerable<{typeof(T)}> as an argument.", Array.Empty<GUILayoutOption>());
					GUILayout.EndHorizontal();
					GUI.changed = false;
					GUILayout.EndVertical();
					GUILayout.FlexibleSpace();
				}
				else
				{
					ICollection<T> collection = (ICollection<T>)constructor.Invoke(new object[1] { entry.BoxedValue });
					AcceptableValueBase acceptableValues = entry.Description.AcceptableValues;
					int num3 = 0;
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					foreach (T item in allElementSupplier())
					{
						if (acceptableValues == null || acceptableValues.IsValid((object)item))
						{
							string text = labelGenerator(item);
							int num4 = Mathf.FloorToInt(GUI.skin.toggle.CalcSize(new GUIContent(text + "_")).x);
							num3 += num4;
							if (num3 > num2)
							{
								GUILayout.EndHorizontal();
								num3 = num4;
								GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
							}
							GUI.changed = false;
							bool flag = GUILayout.Toggle(collection.Contains(item), text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
							if (GUI.changed)
							{
								if (flag)
								{
									collection.Add(item);
								}
								else
								{
									collection.Remove(item);
								}
								entry.BoxedValue = collection;
							}
						}
					}
					GUILayout.EndHorizontal();
					GUI.changed = false;
					GUILayout.EndVertical();
					GUILayout.FlexibleSpace();
				}
			};
		}

		public static void Register(IsMatchConfig matcher, CustomDrawerSupplier supplier)
		{
			CustomDrawers[matcher] = supplier;
		}

		public static Action<ConfigEntryBase> Get(Type type, AcceptableValueBase acceptableValue)
		{
			return (from x in CustomDrawers
				where x.Key(type, acceptableValue)
				select x.Value()).FirstOrDefault();
		}
	}
	public sealed class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;
	}
	public static class Csv
	{
		public sealed class Parser
		{
			private readonly int _end;

			private readonly StringBuilder _fieldBuffer;

			private readonly List<string> _recordBuffer;

			private readonly string _source;

			private int _offset;

			private bool _quoted;

			public Parser(string source, int offset = 0)
			{
				_source = source;
				_end = source.Length - 1;
				_offset = offset;
				_quoted = false;
				_recordBuffer = new List<string>();
				_fieldBuffer = new StringBuilder();
			}

			public List<List<string>> Parse()
			{
				List<List<string>> list = new List<List<string>>();
				int num = -1;
				while (HasNext())
				{
					List<string> list2 = ParseLine();
					int count = list2.Count;
					if (count != 0)
					{
						if (num == -1)
						{
							num = count;
						}
						else if (num != count)
						{
							throw new Exception("Number of fields in a record is not uniform.");
						}
						list.Add(list2);
					}
				}
				return list;
			}

			public bool HasNext()
			{
				return _offset < _source.Length;
			}

			public List<string> ParseLine()
			{
				_recordBuffer.Clear();
				_fieldBuffer.Clear();
				List<string> list = new List<string>();
				while (_offset < _source.Length)
				{
					if (!ParseChar(_source[_offset]))
					{
						_offset++;
						break;
					}
					_offset++;
				}
				if (_fieldBuffer.Length > 0)
				{
					FlushField();
				}
				if (_recordBuffer.Count > 0)
				{
					list.AddRange(_recordBuffer);
				}
				return list;
			}

			private bool ParseChar(char c)
			{
				while (true)
				{
					char c2;
					switch (c)
					{
					case '"':
						if (_quoted && _offset < _end)
						{
							_offset++;
							c2 = _source[_offset];
							if (c2 != '"')
							{
								goto IL_0052;
							}
							_fieldBuffer.Append(c2);
						}
						else
						{
							_quoted = !_quoted && _offset < _end;
						}
						break;
					case ',':
						if (_quoted)
						{
							_fieldBuffer.Append(c);
						}
						else
						{
							FlushField();
						}
						break;
					case '\r':
					{
						int num = Math.Min(_offset + 1, _end);
						if (_source[num] == '\n')
						{
							_offset = num;
						}
						if (!_quoted)
						{
							if (_fieldBuffer.Length > 0)
							{
								FlushField();
							}
							return false;
						}
						_fieldBuffer.Append('\n');
						break;
					}
					case '\n':
						if (!_quoted)
						{
							if (_fieldBuffer.Length > 0)
							{
								FlushField();
							}
							return false;
						}
						_fieldBuffer.Append('\n');
						break;
					default:
						_fieldBuffer.Append(c);
						break;
					}
					break;
					IL_0052:
					_quoted = false;
					c = c2;
				}
				return true;
			}

			private void FlushField()
			{
				_recordBuffer.Add(_fieldBuffer.ToString().Trim());
				_fieldBuffer.Clear();
			}
		}

		private static readonly char[] MustQuoteChars = new char[4] { '"', ',', '\r', '\n' };

		public static string Escape(string field)
		{
			if (field.IndexOfAny(MustQuoteChars) != -1)
			{
				return "\"" + field.Replace("\"", "\"\"") + "\"";
			}
			return field;
		}

		public static List<List<string>> Parse(string csv)
		{
			return new Parser(csv).Parse();
		}

		public static List<string> ParseLine(string line)
		{
			return new Parser(line).ParseLine();
		}
	}
	public class InstanceCache<T> : MonoBehaviour
	{
		private static readonly HashSet<T> Cache;

		private T _instance;

		public static Action<T> OnCacheAdded { get; set; }

		public static Action<T> OnCacheRemoved { get; set; }

		static InstanceCache()
		{
			Cache = new HashSet<T>();
		}

		private void Awake()
		{
			_instance = GetInstance();
			if (_instance != null)
			{
				object obj = _instance;
				Object val = (Object)((obj is Object) ? obj : null);
				if (val == null || Object.op_Implicit(val))
				{
					Cache.Add(_instance);
					OnCacheAdded?.Invoke(_instance);
					return;
				}
			}
			throw new NullReferenceException("Failed to acquire instance.");
		}

		private void OnDestroy()
		{
			Cache.Remove(_instance);
			OnCacheRemoved?.Invoke(_instance);
			_instance = default(T);
		}

		protected virtual T GetInstance()
		{
			return ((Component)this).GetComponent<T>();
		}

		public static IEnumerable<T> GetAllInstance()
		{
			return Cache.ToList();
		}
	}
	public static class Inventories
	{
		public static IEnumerable<ItemData> GetItems(Inventory inventory, string name, int quality = -1, bool isPrefabName = false)
		{
			return from data in inventory.GetAllItems()
				where (isPrefabName ? (((Object)data.m_dropPrefab).name == name) : (data.m_shared.m_name == name)) && (quality < 0 || data.m_quality == quality)
				select data;
		}

		public static int AddItem(Inventory inventory, GameObject prefab, int amount, int quality = -1)
		{
			ItemData val = prefab.GetComponent<ItemDrop>().m_itemData.Clone();
			val.m_dropPrefab = prefab;
			val.m_stack = Mathf.Min(amount, val.m_shared.m_maxStackSize);
			val.m_quality = Mathf.Clamp(quality, 1, val.m_shared.m_maxQuality);
			int num = inventory.CountItems(val.m_shared.m_name, quality, true);
			inventory.AddItem(val);
			return inventory.CountItems(val.m_shared.m_name, quality, true) - num;
		}

		public static int FillFreeStackSpace(Inventory from, Inventory to, string name, float worldLevel, int amount, int quality = -1, bool isPrefabName = false)
		{
			if (amount <= 0)
			{
				return 0;
			}
			int num = Mathf.Min(amount, to.FindFreeStackSpace(name, worldLevel));
			if (num == 0)
			{
				return 0;
			}
			int num2 = 0;
			List<ItemData> list = GetItems(to, name, quality, isPrefabName).ToList();
			foreach (ItemData item in GetItems(from, name, quality, isPrefabName))
			{
				foreach (ItemData item2 in list)
				{
					if (item2.m_stack >= item2.m_shared.m_maxStackSize)
					{
						continue;
					}
					int num3 = Mathf.Min(Mathf.Min(num, item.m_stack), item2.m_shared.m_maxStackSize - item2.m_stack);
					if (num3 != 0)
					{
						item2.m_stack += num3;
						num2 += num3;
						item.m_stack -= num3;
						num -= num3;
						if (item.m_stack == 0)
						{
							from.RemoveItem(item);
						}
						else
						{
							Reflections.InvokeMethod(from, "Changed");
						}
						Reflections.InvokeMethod(to, "Changed");
						if (num == 0)
						{
							goto end_IL_0127;
						}
						if (item.m_stack == 0)
						{
							break;
						}
					}
				}
				continue;
				end_IL_0127:
				break;
			}
			return num2;
		}

		public static int FillFreeStackSpace(Inventory inventory, string name, int amount, int quality = -1, bool isPrefabName = false)
		{
			if (amount <= 0)
			{
				return 0;
			}
			int num = amount;
			int num2 = 0;
			foreach (ItemData item in GetItems(inventory, name, quality, isPrefabName))
			{
				if (item.m_stack >= item.m_shared.m_maxStackSize)
				{
					continue;
				}
				int num3 = Mathf.Min(num, item.m_shared.m_maxStackSize - item.m_stack);
				if (num3 > 0)
				{
					item.m_stack += num3;
					num2 += num3;
					num -= num3;
					Reflections.InvokeMethod(inventory, "Changed");
					if (num == 0)
					{
						break;
					}
				}
			}
			return num2;
		}

		public static bool HaveItem(Inventory inventory, string name, int amount, int quality = -1, bool isPrefabName = false)
		{
			int num = 0;
			foreach (ItemData item in GetItems(inventory, name, quality, isPrefabName))
			{
				num += item.m_stack;
				if (num >= amount)
				{
					return true;
				}
			}
			return false;
		}

		public static int RemoveItem(Inventory inventory, string name, int amount, int quality = -1, bool isPrefabName = false)
		{
			if (amount <= 0)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData item in GetItems(inventory, name, quality, isPrefabName))
			{
				int num2 = Mathf.Min(amount, item.m_stack);
				item.m_stack -= num2;
				num += num2;
				amount -= num2;
				if (item.m_stack == 0)
				{
					inventory.RemoveItem(item);
				}
				else
				{
					Reflections.InvokeMethod(inventory, "Changed");
				}
				if (amount == 0)
				{
					break;
				}
			}
			return num;
		}
	}
	public static class Json
	{
		public static T Parse<T>(string jsonText, ReaderOption option)
		{
			return JsonMapper.ToObject<T>(new JsonReader(jsonText)
			{
				AllowComments = option.AllowComments,
				AllowSingleQuotedStrings = option.AllowSingleQuotedStrings,
				SkipNonMembers = option.SkipNonMembers
			});
		}

		public static T Parse<T>(string jsonText)
		{
			return Parse<T>(jsonText, new ReaderOption
			{
				AllowComments = true,
				AllowSingleQuotedStrings = false,
				SkipNonMembers = true
			});
		}

		public static string ToString(object obj, WriterOption option)
		{
			StringBuilder stringBuilder = new StringBuilder();
			JsonMapper.ToJson(obj, new JsonWriter(stringBuilder)
			{
				IndentValue = option.IndentSize,
				PrettyPrint = option.Pretty
			});
			return stringBuilder.ToString();
		}

		public static string ToString(object obj)
		{
			return ToString(obj, new WriterOption
			{
				Pretty = false,
				IndentSize = 0
			});
		}
	}
	public struct ReaderOption
	{
		public bool AllowComments;

		public bool AllowSingleQuotedStrings;

		public bool SkipNonMembers;
	}
	public struct WriterOption
	{
		public bool Pretty;

		public int IndentSize;
	}
	public class L10N
	{
		private static readonly Regex InternalNamePattern;

		private static readonly Regex WordPattern;

		private static readonly Localization Localization;

		private readonly string _prefix;

		static L10N()
		{
			InternalNamePattern = new Regex("^(\\$|@)(\\w|\\d|[^\\s(){}[\\]+\\-!?/\\\\&%,.:=<>])+$", RegexOptions.Compiled);
			WordPattern = new Regex("(\\$|@)((?:\\w|\\d|[^\\s(){}[\\]+\\-!?/\\\\&%,.:=<>])+)", RegexOptions.Compiled);
			Localization = Localization.instance;
		}

		public L10N(string prefix)
		{
			_prefix = prefix;
		}

		private static string InvokeTranslate(string word)
		{
			return Reflections.InvokeMethod<string>(Localization, "Translate", new object[1] { word });
		}

		private static string InvokeInsertWords(string text, string[] words)
		{
			return Reflections.InvokeMethod<string>(Localization, "InsertWords", new object[2] { text, words });
		}

		private static void InvokeAddWord(string key, string word)
		{
			Reflections.InvokeMethod(Localization, "AddWord", key, word);
		}

		internal static string GetTranslationKey(string prefix, string internalName)
		{
			if (string.IsNullOrEmpty(internalName))
			{
				return "";
			}
			return internalName[0] switch
			{
				'$' => internalName.Substring(1), 
				'@' => prefix + "_" + internalName.Substring(1), 
				_ => internalName, 
			};
		}

		internal static string Translate(string prefix, string word)
		{
			return InvokeTranslate(GetTranslationKey(prefix, word));
		}

		public static bool IsInternalName(string text)
		{
			if (!string.IsNullOrEmpty(text))
			{
				return InternalNamePattern.IsMatch(text);
			}
			return false;
		}

		private string GetTranslationKey(string internalName)
		{
			return GetTranslationKey(_prefix, internalName);
		}

		public void AddWord(string key, string word)
		{
			InvokeAddWord(GetTranslationKey(key), word);
		}

		public string Translate(string word)
		{
			return InvokeTranslate(GetTranslationKey(word));
		}

		public string TranslateInternalName(string internalName)
		{
			if (IsInternalName(internalName))
			{
				return InvokeTranslate(GetTranslationKey(internalName));
			}
			return internalName;
		}

		public string Localize(string text)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			foreach (Match item in WordPattern.Matches(text))
			{
				GroupCollection groups = item.Groups;
				string word = ((groups[1].Value == "@") ? (_prefix + "_" + groups[2].Value) : groups[2].Value);
				stringBuilder.Append(text.Substring(num, groups[0].Index - num));
				stringBuilder.Append(InvokeTranslate(word));
				num = groups[0].Index + groups[0].Value.Length;
			}
			return stringBuilder.ToString();
		}

		public string Localize(string text, params object[] args)
		{
			return InvokeInsertWords(Localize(text), Array.ConvertAll(args, (object arg) => (!(arg is string internalName)) ? arg.ToString() : TranslateInternalName(internalName)));
		}

		public string LocalizeTextOnly(string text, params object[] args)
		{
			return InvokeInsertWords(Localize(text), Array.ConvertAll(args, (object arg) => (arg as string) ?? arg.ToString()));
		}
	}
	public class TranslationsLoader
	{
		private static readonly Localization Localization;

		private static readonly string DefaultLanguage;

		private static readonly string JsonFilePattern;

		private readonly L10N _localization;

		private Dictionary<string, TranslationsFile> _cache;

		private Logger _logger;

		static TranslationsLoader()
		{
			Localization = Localization.instance;
			DefaultLanguage = "English";
			JsonFilePattern = "*.json";
		}

		public TranslationsLoader(L10N localization)
		{
			_localization = localization;
		}

		public void SetDebugLogger(Logger logger)
		{
			_logger = logger;
		}

		private bool LoadAllFile(string directory, string filePattern, string language, Func<string, string, bool> loading)
		{
			_logger?.Debug("Load translation files for " + language + " from directory: [directory: " + directory + ", file pattern: " + filePattern + "]");
			return Directory.EnumerateFiles(directory, filePattern, SearchOption.AllDirectories).Count((string path) => loading(path, language)) > 0;
		}

		public void LoadJson(string languagesDir)
		{
			_cache = new Dictionary<string, TranslationsFile>();
			if (!Directory.Exists(languagesDir))
			{
				_logger?.Error("Directory does not exist: " + languagesDir);
				return;
			}
			string selectedLanguage = Localization.GetSelectedLanguage();
			if (selectedLanguage != DefaultLanguage && !LoadAllFile(languagesDir, JsonFilePattern, DefaultLanguage, ReadJsonFile))
			{
				_logger?.Warning("Directory does not contain a translation file for the default language: " + languagesDir);
			}
			if (!LoadAllFile(languagesDir, JsonFilePattern, selectedLanguage, ReadJsonFile))
			{
				_logger?.Warning("Directory does not contain a translation file for the " + selectedLanguage + ": " + languagesDir);
			}
			_cache = null;
		}

		private bool ReadJsonFile(string path, string language)
		{
			if (!_cache.TryGetValue(path, out var value))
			{
				try
				{
					value = Json.Parse<TranslationsFile>(File.ReadAllText(path));
					_cache.Add(path, value);
				}
				catch (Exception arg)
				{
					_logger?.Error($"Failed to read Json file\n{arg}");
					_cache.Add(path, default(TranslationsFile));
					return false;
				}
			}
			if (!string.Equals(value.language, language, StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			_logger?.Debug("Load translations: " + path);
			foreach (KeyValuePair<string, string> translation in value.translations)
			{
				_localization.AddWord(translation.Key, translation.Value);
			}
			return true;
		}
	}
	[Serializable]
	public struct TranslationsFile
	{
		public string language;

		public Dictionary<string, string> translations;
	}
	public class Logger
	{
		private readonly Func<LogLevel, bool> _isEnabled;

		private readonly ManualLogSource _logger;

		public Logger(ManualLogSource logger, Func<LogLevel, bool> isEnabled)
		{
			_logger = logger;
			_isEnabled = isEnabled;
		}

		private void Log(LogLevel level, string message)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (_isEnabled(level))
			{
				_logger.Log(level, (object)message);
			}
		}

		private void Log(LogLevel level, Func<string> message)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (_isEnabled(level))
			{
				_logger.Log(level, (object)message());
			}
		}

		public void Fatal(Func<string> message)
		{
			Log((LogLevel)1, message);
		}

		public void Fatal(string message)
		{
			Log((LogLevel)1, message);
		}

		public void Error(Func<string> message)
		{
			Log((LogLevel)2, message);
		}

		public void Error(string message)
		{
			Log((LogLevel)2, message);
		}

		public void Warning(Func<string> message)
		{
			Log((LogLevel)4, message);
		}

		public void Warning(string message)
		{
			Log((LogLevel)4, message);
		}

		public void Info(Func<string> message)
		{
			Log((LogLevel)16, message);
		}

		public void Info(string message)
		{
			Log((LogLevel)16, message);
		}

		public void Message(Func<string> message)
		{
			Log((LogLevel)8, message);
		}

		public void Message(string message)
		{
			Log((LogLevel)8, message);
		}

		public void Debug(Func<string> message)
		{
			Log((LogLevel)32, message);
		}

		public void Debug(string message)
		{
			Log((LogLevel)32, message);
		}
	}
	public abstract class ObjectNode<TNode, TNetwork> : MonoBehaviour where TNode : ObjectNode<TNode, TNetwork> where TNetwork : ObjectNetwork<TNode, TNetwork>
	{
		protected static readonly HashSet<TNode> ObjectNodes;

		private TNode This => (TNode)this;

		public TNetwork Network { get; set; }

		static ObjectNode()
		{
			ObjectNodes = new HashSet<TNode>();
		}

		protected virtual void Awake()
		{
			ObjectNodes.Add(This);
			((MonoBehaviour)this).Invoke("NetworkConstruction", Random.Range(1f, 2f));
		}

		protected virtual void OnDestroy()
		{
			ObjectNodes.Remove(This);
			Network?.RemoveNode(This);
			Network = null;
		}

		protected abstract TNetwork CreateNetwork();

		protected abstract bool IsConnectable(TNode other);

		private void NetworkConstruction()
		{
			foreach (TNode item in ObjectNodes.Where(IsConnectable))
			{
				if (Network == item.Network)
				{
					continue;
				}
				if (Network == null)
				{
					Network = item.Network;
					Network.AddNode(This);
					continue;
				}
				if (item.Network == null)
				{
					item.Network = Network;
					item.Network.AddNode(item);
					continue;
				}
				TNetwork obj = ((Network.NodeCount >= item.Network.NodeCount) ? item.Network : Network);
				TNetwork network = ((Network.NodeCount >= item.Network.NodeCount) ? Network : item.Network);
				foreach (TNode allNode in obj.GetAllNodes())
				{
					allNode.Network.RemoveNode(allNode);
					allNode.Network = network;
					allNode.Network.AddNode(allNode);
				}
			}
			if (Network == null)
			{
				Network = CreateNetwork();
				Network.AddNode(This);
			}
		}
	}
	public class ObjectNetwork<TNode, TNetwork> where TNode : ObjectNode<TNode, TNetwork> where TNetwork : ObjectNetwork<TNode, TNetwork>
	{
		private readonly HashSet<TNode> _nodes;

		protected Action<IEnumerable<TNode>> OnNodeChanged { get; set; }

		public bool IsDirty { get; private set; }

		public int NodeCount => _nodes.Count;

		protected ObjectNetwork()
		{
			_nodes = new HashSet<TNode>();
		}

		public IEnumerable<TNode> GetAllNodes()
		{
			return _nodes.ToList();
		}

		public void AddNode(TNode node)
		{
			if (_nodes.Add(node))
			{
				IsDirty = true;
			}
		}

		public void RemoveNode(TNode node)
		{
			if (_nodes.Remove(node))
			{
				IsDirty = true;
			}
		}

		public void Update()
		{
			if (IsDirty)
			{
				OnNodeChanged?.Invoke(GetAllNodes());
				IsDirty = false;
			}
		}
	}
	public static class Objects
	{
		private static readonly ConditionalWeakTable<Component, ZNetView> ZNetViewCache;

		private static readonly ConditionalWeakTable<Component, string> NameCache;

		static Objects()
		{
			ZNetViewCache = new ConditionalWeakTable<Component, ZNetView>();
			NameCache = new ConditionalWeakTable<Component, string>();
		}

		public static string GetPrefabName(GameObject gameObject)
		{
			return Utils.GetPrefabName(gameObject);
		}

		public static string GetName(Component component)
		{
			if (!Object.op_Implicit((Object)(object)component))
			{
				return "";
			}
			if (NameCache.TryGetValue(component, out var value))
			{
				return value;
			}
			value = (from x in ((object)component).GetType().GetFields(AccessTools.all)
				where x.Name == "m_name" && x.FieldType == typeof(string)
				select x.GetValue(component) as string).FirstOrDefault();
			if (string.IsNullOrEmpty(value))
			{
				Hoverable component2 = component.GetComponent<Hoverable>();
				if (component2 != null)
				{
					HoverText val = (HoverText)(object)((component2 is HoverText) ? component2 : null);
					value = ((val != null) ? val.m_text : component2.GetHoverName());
				}
				if (string.IsNullOrEmpty(value))
				{
					value = Utils.GetPrefabName(component.gameObject);
				}
			}
			NameCache.Add(component, value);
			return value;
		}

		public static bool GetZNetView(Component component, out ZNetView zNetView)
		{
			if (!Object.op_Implicit((Object)(object)component))
			{
				zNetView = null;
				return false;
			}
			if (ZNetViewCache.TryGetValue(component, out zNetView))
			{
				return Object.op_Implicit((Object)(object)zNetView);
			}
			zNetView = (from x in ((object)component).GetType().GetFields(AccessTools.all)
				where x.Name == "m_nview" && x.FieldType == typeof(ZNetView)
				select x).Select(delegate(FieldInfo x)
			{
				object? value = x.GetValue(component);
				return (ZNetView)((value is ZNetView) ? value : null);
			}).FirstOrDefault() ?? component.GetComponent<ZNetView>();
			ZNetViewCache.Add(component, zNetView);
			return (Object)(object)zNetView != (Object)null;
		}

		public static bool GetZdoid(Component component, out ZDOID id)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			id = (GetZNetView(component, out var zNetView) ? zNetView.GetZDO() : null)?.m_uid ?? ZDOID.None;
			return id != ZDOID.None;
		}

		public static float Distance(Component obj1, Component obj2)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.Distance(obj1.transform.position, obj2.transform.position);
		}

		public static List<(Collider collider, T obj, float distance)> GetInsideSphere<T>(Vector3 origin, float radius, Func<Collider, T> convertor, Collider[] buffer, int layerMask = -1)
		{
			//IL_0006: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			List<(Collider, T, float)> list = new List<(Collider, T, float)>();
			int num = Physics.OverlapSphereNonAlloc(origin, radius, buffer, layerMask);
			for (int i = 0; i < num; i++)
			{
				Collider val = buffer[i];
				T val2 = convertor(val);
				if (val2 != null)
				{
					list.Add((val, val2, Vector3.Distance(origin, ((Component)val).transform.position)));
				}
			}
			return list;
		}

		public static List<(Collider collider, T obj, float distance)> GetInsideSphere<T>(Vector3 origin, float radius, Func<Collider, T> convertor, int bufferSize = 128, int layerMask = -1)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return GetInsideSphere(origin, radius, convertor, (Collider[])(object)new Collider[bufferSize], layerMask);
		}
	}
	public static class Reflections
	{
		public static TR InvokeStaticMethod<T, TR>(string methodName, params object[] args)
		{
			return Traverse.Create<T>().Method(methodName, args).GetValue<TR>(args);
		}

		public static void InvokeStaticMethod<T>(string methodName, params object[] args)
		{
			Traverse.Create<T>().Method(methodName, args).GetValue(args);
		}

		public static TR InvokeStaticMethod<T, TR>(string methodName)
		{
			return Traverse.Create<T>().Method(methodName, Array.Empty<object>()).GetValue<TR>();
		}

		public static void InvokeStaticMethod<T>(string methodName)
		{
			Traverse.Create<T>().Method(methodName, Array.Empty<object>()).GetValue();
		}

		public static T InvokeMethod<T>(object instance, string methodName, params object[] args)
		{
			return Traverse.Create(instance).Method(methodName, args).GetValue<T>(args);
		}

		public static void InvokeMethod(object instance, string methodName, params object[] args)
		{
			Traverse.Create(instance).Method(methodName, args).GetValue(args);
		}

		public static T InvokeMethod<T>(object instance, string methodName)
		{
			return Traverse.Create(instance).Method(methodName, Array.Empty<object>()).GetValue<T>();
		}

		public static void InvokeMethod(object instance, string methodName)
		{
			Traverse.Create(instance).Method(methodName, Array.Empty<object>()).GetValue();
		}

		public static TType GetStaticField<TClass, TType>(string fieldName)
		{
			return Traverse.Create<TClass>().Field<TType>(fieldName).Value;
		}

		public static TType SetStaticField<TClass, TType>(string fieldName, TType value)
		{
			return Traverse.Create<TClass>().Field<TType>(fieldName).Value = value;
		}

		public static T GetField<T>(object instance, string fieldName)
		{
			return Traverse.Create(instance).Field<T>(fieldName).Value;
		}

		public static void SetField<T>(object instance, string fieldName, T value)
		{
			Traverse.Create(instance).Field<T>(fieldName).Value = value;
		}
	}
	public class SpriteLoader
	{
		private static readonly Dictionary<string, Texture2D> TextureCache;

		private Logger _logger;

		static SpriteLoader()
		{
			TextureCache = new Dictionary<string, Texture2D>();
		}

		private static Sprite CreateSprite(Texture2D texture, int width, int height)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			return Sprite.Create(texture, new Rect(0f, 0f, (float)width, (float)height), Vector2.zero);
		}

		public static string GetTextureFileName(Sprite sprite)
		{
			using (IEnumerator<KeyValuePair<string, Texture2D>> enumerator = TextureCache.Where((KeyValuePair<string, Texture2D> pair) => (Object)(object)pair.Value == (Object)(object)sprite.texture).GetEnumerator())
			{
				if (enumerator.MoveNext())
				{
					return Path.GetFileName(enumerator.Current.Key);
				}
			}
			return "";
		}

		public void SetDebugLogger(Logger logger)
		{
			_logger = logger;
		}

		public Sprite Load(string texturePath, int width, int height)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			if (!File.Exists(texturePath))
			{
				return null;
			}
			if (TextureCache.TryGetValue(texturePath, out var value))
			{
				if (!((Object)(object)value != (Object)null))
				{
					return null;
				}
				return CreateSprite(value, width, height);
			}
			try
			{
				_logger?.Info("Try to create sprite: " + texturePath);
				Texture2D val = new Texture2D(0, 0);
				ImageConversion.LoadImage(val, File.ReadAllBytes(texturePath));
				TextureCache.Add(texturePath, val);
				return CreateSprite(val, width, height);
			}
			catch (Exception arg)
			{
				_logger?.Error($"Failed to create sprite: {texturePath}\n{arg}");
				TextureCache.Add(texturePath, null);
				return null;
			}
		}
	}
}
namespace Automatics
{
	[BepInPlugin("net.eidee.valheim.automatics", "Automatics", "1.5.1")]
	public class UnityPlugin : BaseUnityPlugin
	{
		private const string ModId = "net.eidee.valheim.automatics";

		private const string ModName = "Automatics";

		private const string ModVersion = "1.5.1";

		private void Awake()
		{
			Automatics.Initialize((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger);
		}
	}
	internal static class Automatics
	{
		public const string L10NPrefix = "automatics";

		private static string _modLocation;

		private static string _guid;

		private static List<string> _allResourcesDirectory;

		public static BaseUnityPlugin Plugin { get; private set; }

		public static Logger Logger { get; private set; }

		public static L10N L10N { get; private set; }

		private static IEnumerable<string> GetAllResourcesDirectory()
		{
			if (_allResourcesDirectory != null)
			{
				return _allResourcesDirectory;
			}
			_allResourcesDirectory = new List<string> { _modLocation };
			string pluginPath = Paths.PluginPath;
			if (!Directory.Exists(pluginPath))
			{
				return _allResourcesDirectory;
			}
			string[] directories = Directory.GetDirectories(pluginPath);
			foreach (string text in directories)
			{
				if (File.Exists(Path.Combine(text, "automatics-child-mod")))
				{
					_allResourcesDirectory.Add(text);
				}
				else if (File.Exists(Path.Combine(text, "automatics-resources-marker")))
				{
					_allResourcesDirectory.Add(text);
				}
			}
			return _allResourcesDirectory;
		}

		private static void InitializeModules(Assembly assembly)
		{
			foreach (var item2 in from x in ((IEnumerable<Type>)AccessTools.GetTypesFromAssembly(assembly)).SelectMany((Func<Type, IEnumerable<MethodInfo>>)AccessTools.GetDeclaredMethods)
				select (x, x.GetCustomAttributes(typeof(AutomaticsInitializerAttribute), inherit: false).OfType<AutomaticsInitializerAttribute>().FirstOrDefault()) into x
				where x.Item2 != null
				orderby x.Item2.Order
				select x)
			{
				MethodInfo item = item2.Item1;
				try
				{
					item.Invoke(null, new object[0]);
				}
				catch (Exception arg)
				{
					Logger.Error($"Error while initializing {item.Name}\n{arg}");
				}
			}
		}

		public static IEnumerable<string> GetAllResourcePath(string pathname)
		{
			return from x in GetAllResourcesDirectory()
				select Path.Combine(x, pathname);
		}

		public static string GetHarmonyId(string moduleName)
		{
			return _guid + "." + moduleName;
		}

		public static void Initialize(BaseUnityPlugin plugin, ManualLogSource logger)
		{
			Plugin = plugin;
			Logger = new Logger(logger, Config.IsLogEnabled);
			_modLocation = Path.GetDirectoryName(Plugin.Info.Location) ?? "";
			_guid = Plugin.Info.Metadata.GUID;
			Logger.Debug("Mod location: " + _modLocation);
			ConfigMigration.Migration(Plugin.Config);
			ValheimObject.Initialize(GetAllResourcePath("Data"));
			L10N = new L10N("automatics");
			TranslationsLoader translationsLoader = new TranslationsLoader(L10N);
			foreach (string item in GetAllResourcePath("Languages"))
			{
				translationsLoader.LoadJson(item);
			}
			Config.Initialize(Plugin.Config);
			Hooks.OnInitTerminal = (Action)Delegate.Combine(Hooks.OnInitTerminal, new Action(Commands.Register));
			Harmony.CreateAndPatchAll(typeof(Patches), _guid);
			InitializeModules(Assembly.GetExecutingAssembly());
			ValheimObject.PostInitialize();
		}
	}
	[AttributeUsage(AttributeTargets.Method)]
	[MeansImplicitUse]
	public class AutomaticsInitializerAttribute : Attribute
	{
		public int Order { get; }

		public AutomaticsInitializerAttribute(int order = 0)
		{
			Order = order;
		}
	}
	internal static class Commands
	{
		public static void Register()
		{
			new ShowCommands().Register();
			new PrintNames().Register();
			new PrintObjects().Register();
			new RemoveMapPins().Register();
		}
	}
	internal static class Config
	{
		private const int NexusID = 1700;

		private static ConfigEntry<bool> _logEnabled;

		private static ConfigEntry<LogLevel> _allowedLogLevel;

		public static bool LogEnabled => _logEnabled.Value;

		public static LogLevel AllowedLogLevel => _allowedLogLevel.Value;

		public static bool Initialized { get; private set; }

		public static Configuration Instance { get; private set; }

		public static bool IsLogEnabled(LogLevel level)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			if (Initialized)
			{
				if (LogEnabled)
				{
					return (AllowedLogLevel & level) > 0;
				}
				return false;
			}
			return true;
		}

		public static ConfigEntry<List<ObjectElement>> BindCustomValheimObject(this Configuration config, string key, ValheimObject obj)
		{
			ConfigEntry<List<ObjectElement>> entry = config.Bind(key, new List<ObjectElement>());
			if (entry.Value.Any())
			{
				obj.RegisterCustom(entry.Value);
			}
			entry.SettingChanged += delegate
			{
				obj.RegisterCustom(entry.Value);
			};
			return entry;
		}

		public static ConfigEntry<StringList> BindValheimObjectList(this Configuration config, string key, ValheimObject obj, IEnumerable<string> defaults = null, IEnumerable<string> includes = null, IEnumerable<string> excludes = null)
		{
			List<string> list = new List<string>();
			list.AddRange(defaults ?? (from x in obj.GetAllElements()
				select x.identifier));
			if (includes != null)
			{
				list.RemoveAll((string x) => !includes.Contains(x));
			}
			if (excludes != null)
			{
				list.RemoveAll(excludes.Contains<string>);
			}
			return config.Bind(key, new StringList(list), null, delegate(ConfigurationManagerAttributes x)
			{
				x.CustomDrawer = ConfigurationCustomDrawer.MultiSelect(() => from y in obj.GetAllElements()
					select y.identifier, (string identifier) => (!obj.GetName(identifier, out var name)) ? "INTERNAL ERROR" : Automatics.L10N.TranslateInternalName(name));
			});
		}

		public static void Initialize(ConfigFile config)
		{
			if (!Initialized)
			{
				Instance = new Configuration(config, Automatics.L10N);
				Instance.ChangeSection("hidden");
				Instance.Bind("NexusID", 1700, null, delegate(ConfigurationManagerAttributes x)
				{
					x.Browsable = false;
					x.ReadOnly = true;
				});
				Instance.ChangeSection("system");
				_logEnabled = Instance.Bind("enable_logging", defaultValue: false);
				_allowedLogLevel = Instance.Bind<LogLevel>("log_level_to_allow_logging", (LogLevel)15);
				Instance.ChangeSection("general");
				Instance.BindCustomValheimObject("custom_animal", ValheimObject.Animal);
				Instance.BindCustomValheimObject("custom_dungeon", ValheimObject.Dungeon);
				Instance.BindCustomValheimObject("custom_flora", ValheimObject.Flora);
				Instance.BindCustomValheimObject("custom_mineral", ValheimObject.Mineral);
				Instance.BindCustomValheimObject("custom_monster", ValheimObject.Monster);
				Instance.BindCustomValheimObject("custom_spawner", ValheimObject.Spawner);
				Instance.BindCustomValheimObject("custom_spot", ValheimObject.Spot);
				Initialized = true;
			}
		}
	}
	public enum AutomaticsModule
	{
		[LocalizedDescription("automatics", "@message_module_enabled")]
		Enabled,
		[LocalizedDescription("automatics", "@message_module_disabled")]
		Disabled
	}
	public enum Message
	{
		[LocalizedDescription("automatics", "@message_none")]
		None,
		[LocalizedDescription("automatics", "@message_center")]
		Center,
		[LocalizedDescription("automatics", "@message_top_left")]
		TopLeft
	}
	internal static class ConfigMigration
	{
		private class Config
		{
			public int Offset;

			public string Category;

			public string Key;

			public string Value;
		}

		private delegate bool Operation(string category, List<string> lines, int begin, int end);

		private readonly struct Version : IComparable<Version>
		{
			private readonly int _major;

			private readonly int _minor;

			private readonly int _patch;

			public Version(int major, int minor, int patch)
			{
				_major = major;
				_minor = minor;
				_patch = patch;
			}

			public override string ToString()
			{
				return $"v{_major}.{_minor}.{_patch}";
			}

			public int CompareTo(Version other)
			{
				int major;
				if (_major != other._major)
				{
					major = _major;
					return major.CompareTo(other._major);
				}
				if (_minor == other._minor)
				{
					major = _patch;
					return major.CompareTo(other._patch);
				}
				major = _minor;
				return major.CompareTo(other._minor);
			}

			public static bool operator >(Version a, Version b)
			{
				return a.CompareTo(b) > 0;
			}

			public static bool operator <(Version a, Version b)
			{
				return a.CompareTo(b) < 0;
			}
		}

		private static readonly Regex VersionPattern;

		private static readonly char[] KeyValueSeparator;

		private static readonly Dictionary<string, List<Config>> ConfigCache;

		static ConfigMigration()
		{
			VersionPattern = new Regex("v(\\d+)\\.(\\d+)\\.(\\d+)$", RegexOptions.Compiled);
			KeyValueSeparator = new char[1] { '=' };
			ConfigCache = new Dictionary<string, List<Config>>();
		}

		private static Operation RenameCategory(string newCategory)
		{
			return delegate(string category, List<string> lines, int begin, int end)
			{
				string text = lines[begin];
				lines[begin] = newCategory;
				Automatics.Logger.Message("Rename category: " + text + " => " + newCategory);
				return true;
			};
		}

		private static Operation RemoveConfig(string key)
		{
			return delegate(string category, List<string> lines, int begin, int end)
			{
				foreach (Config item in FindConfig(category, key, lines, begin, end))
				{
					string key2 = item.Key;
					item.Key = "";
					UpdateConfig(item, lines);
					Automatics.Logger.Message("Remove config: " + category + " " + key2);
				}
				return true;
			};
		}

		private static Operation RenameConfig(string key, string newKey)
		{
			return delegate(string category, List<string> lines, int begin, int end)
			{
				foreach (Config item in FindConfig(category, key, lines, begin, end))
				{
					string key2 = item.Key;
					item.Key = (GetMatcher(key).IsRegex ? Regex.Replace(key, key, newKey) : newKey);
					UpdateConfig(item, lines);
					Automatics.Logger.Message("Rename config: " + category + " " + key2 + " => " + item.Key);
				}
				return true;
			};
		}

		private static Operation ReplaceValue(string key, string value, string newValue)
		{
			return delegate(string category, List<string> lines, int begin, int end)
			{
				foreach (Config item in from x in FindConfig(category, key, lines, begin, end)
					where string.Equals(x.Value, value, StringComparison.OrdinalIgnoreCase)
					select x)
				{
					string value2 = item.Value;
					item.Value = newValue;
					UpdateConfig(item, lines);
					Automatics.Logger.Message("Replace value: " + category + " " + key + " " + value2 + " => " + newValue);
				}
				return true;
			};
		}

		private static IEnumerable<Config> FindConfig(string category, string key, List<string> lines, int begin = 0, int end = int.MaxValue)
		{
			(bool IsRegex, string Pattern) matcher = GetMatcher(key);
			if (ConfigCache.TryGetValue(category, out var value))
			{
				return value.Where((Config x) => x.Category == category && IsMatch(x.Key, matcher));
			}
			end = Mathf.Min(end, lines.Count);
			begin = Mathf.Clamp(begin, 0, end);
			value = new List<Config>(0);
			string text = "";
			int i;
			for (i = begin; i < end; i++)
			{
				string text2 = lines[i];
				if (text2.StartsWith("#"))
				{
					continue;
				}
				if (Regex.IsMatch(text2, "^\\[[\\w\\d_]+\\]$"))
				{
					text = text2;
					if (!ConfigCache.TryGetValue(text, out value))
					{
						value = new List<Config>();
						ConfigCache[text] = value;
					}
				}
				else if (!value.Any((Config x) => x.Offset == i))
				{
					string[] array = text2.Split(KeyValueSeparator, 2, StringSplitOptions.None);
					if (array.Length == 2)
					{
						Config item = new Config
						{
							Offset = i,
							Category = text,
							Key = array[0].Trim(),
							Value = array[1].Trim()
						};
						value.Add(item);
					}
				}
			}
			if (ConfigCache.TryGetValue(category, out value))
			{
				return value.Where((Config x) => x.Category == category && IsMatch(x.Key, matcher));
			}
			Automatics.Logger.Warning("No config matching condition exists: " + category + " / " + key);
			return Array.Empty<Config>();
		}

		private static void UpdateConfig(Config config, List<string> lines)
		{
			if (config.Offset >= 0 || config.Offset < lines.Count)
			{
				if (string.IsNullOrEmpty(config.Key))
				{
					lines[config.Offset] = "";
				}
				else
				{
					lines[config.Offset] = config.Key + " = " + config.Value;
				}
			}
		}

		private static (bool IsRegex, string Pattern) GetMatcher(string pattern)
		{
			if (string.IsNullOrEmpty(pattern))
			{
				return (false, "");
			}
			if (!pattern.StartsWith("r/"))
			{
				return (false, pattern);
			}
			return (true, pattern.Substring(2));
		}

		private static bool IsMatch(string value, (bool IsRegex, string Pattern) matcher)
		{
			if (!matcher.IsRegex)
			{
				if (!string.IsNullOrEmpty(matcher.Pattern))
				{
					return string.Equals(value, matcher.Pattern, StringComparison.OrdinalIgnoreCase);
				}
				return false;
			}
			return Regex.IsMatch(value, matcher.Pattern, RegexOptions.IgnoreCase);
		}

		public static void Migration(ConfigFile config)
		{
			string configFilePath = config.ConfigFilePath;
			if (!File.Exists(configFilePath))
			{
				Automatics.Logger.Error("Config file not found: " + configFilePath);
				return;
			}
			List<string> list = File.ReadAllLines(configFilePath).ToList();
			bool flag = false;
			Version version = ParseVersion(list[0]);
			Version version2 = new Version(1, 3, 0);
			if (version < version2)
			{
				Automatics.Logger.Message($"Migrating config from {version} to {version2}");
				flag = true;
				MigrationFor130(list);
			}
			version2 = new Version(1, 4, 0);
			if (version < version2)
			{
				Automatics.Logger.Message($"Migrating config from {version} to {version2}");
				flag = true;
				MigrationFor140(list);
			}
			version2 = new Version(1, 4, 5);
			if (version < version2)
			{
				Automatics.Logger.Message($"Migrating config from {version} to {version2}");
				flag = true;
				MigrationFor145(list);
			}
			if (flag)
			{
				File.WriteAllText(configFilePath, string.Join(Environment.NewLine, list), Encoding.UTF8);
				config.Reload();
			}
		}

		private static void MigrationFor130(List<string> lines)
		{
			Migration(lines, new Dictionary<string, List<Operation>>
			{
				{
					"[logging]",
					new List<Operation>
					{
						RenameCategory("[system]"),
						RenameConfig("logging_enabled", "enable_logging"),
						RenameConfig("allowed_log_level", "log_level_to_allow_logging")
					}
				},
				{
					"[automatic_door]",
					new List<Operation>
					{
						RenameConfig("automatic_door_enabled", "enable_automatic_door"),
						RenameConfig("player_search_radius_to_open", "distance_for_automatic_opening"),
						RenameConfig("player_search_radius_to_close", "distance_for_automatic_closing"),
						RenameConfig("toggle_automatic_door_enabled_key", "automatic_door_enable_disable_toggle")
					}
				},
				{
					"[automatic_map_pinning]",
					new List<Operation>
					{
						RenameCategory("[automatic_mapping]"),
						RenameConfig("automatic_map_pinning_enabled", "enable_automatic_mapping"),
						RenameConfig("allow_pinning_vein", "allow_pinning_deposit"),
						RenameConfig("allow_pinning_vein_custom", "allow_pinning_deposit_custom"),
						RenameConfig("ignore_tamed_animals", "not_pinning_tamed_animals"),
						RenameConfig("in_ground_veins_need_wishbone", "need_to_equip_wishbone_for_underground_deposits")
					}
				},
				{
					"[automatic_processing]",
					new List<Operation>
					{
						RenameConfig("automatic_processing_enabled", "enable_automatic_processing"),
						RenameConfig("r/^([\\w_]+)_allow_automatic_processing", "allow_processing_by_$1"),
						RenameConfig("r/^([\\w_]+)_container_search_range", "container_search_range_by_$1"),
						RenameConfig("r/^([\\w_]+)_material_count_that_suppress_automatic_process", "$1_material_count_of_suppress_processing"),
						RenameConfig("r/^([\\w_]+)_fuel_count_that_suppress_automatic_process", "$1_fuel_count_of_suppress_processing"),
						RenameConfig("r/^([\\w_]+)_product_count_that_suppress_automatic_store", "$1_product_count_of_suppress_processing")
					}
				},
				{
					"[automatic_feeding]",
					new List<Operation>
					{
						RenameConfig("automatic_feeding_enabled", "enable_automatic_feeding"),
						RenameConfig("need_close_to_eat_the_feed", "need_get_close_to_eat_the_feed"),
						RenameConfig("automatic_repair_enabled", "enable_automatic_repair")
					}
				}
			});
		}

		private static void MigrationFor140(List<string> lines)
		{
			Migration(lines, new Dictionary<string, List<Operation>>
			{
				{
					"[automatic_door]",
					new List<Operation>
					{
						RemoveConfig("allow_automatic_door_custom"),
						ReplaceValue("allow_automatic_door", "All", "WoodDoor, WoodGate, IronGate, DarkwoodGate, WoodShutter")
					}
				},
				{
					"[automatic_mapping]",
					new List<Operation>
					{
						RenameConfig("dynamic_object_search_range", "dynamic_object_mapping_range"),
						RenameConfig("static_object_search_range", "static_object_mapping_range"),
						RenameConfig("location_search_range", "location_mapping_range"),
						RenameConfig("allow_pinning_deposit", "allow_pinning_mineral"),
						RemoveConfig("allow_pinning_ship"),
						RemoveConfig("r/^allow_pinning_[\\w]+_custom$"),
						RenameConfig("static_object_search_interval", "static_object_mapping_interval"),
						RenameConfig("need_to_equip_wishbone_for_underground_deposits", "need_to_equip_wishbone_for_underground_minerals"),
						RenameConfig("static_object_search_key", "static_object_mapping_key"),
						ReplaceValue("allow_pinning_animal", "All", "Boar, Piggy, Deer, Wolf, WolfCub, Lox, LoxCalf, Hen, Chicken, Hare, Bird, Fish"),
						ReplaceValue("allow_pinning_monster", "All", "Greyling, Neck, Ghost, Greydwarf, GreydwarfBrute, GreydwarfShaman, RancidRemains, Skeleton, Troll, Abomination, Blob, Draugr, DraugrElite, Leech, Oozer, Surtling, Wraith, Drake, Fenring, StoneGolem, Deathsquito, Fuling, FulingBerserker, FulingShaman, Growth, Serpent, Bat, FenringCultist, Ulv, DvergrRogue, DvergrMage, Tick, Seeker, SeekerBrood, Gjall, SeekerSoldier"),
						ReplaceValue("allow_pinning_flora", "All", "Dandelion, Mushroom, Raspberries, Blueberries, Carrot, CarrotSeeds, YellowMushroom, Thistle, Turnip, TurnipSeeds, Onion, OnionSeeds, Barley, Cloudberries, Flex, JotunPuffs, Magecap"),
						ReplaceValue("allow_pinning_mineral", "All", "CopperDeposit, TinDeposit, MudPile, ObsidianDeposit, SilverVein, PetrifiedBone, SoftTissue"),
						ReplaceValue("allow_pinning_spawner", "All", "GreydwarfNest, EvilBonePile, BodyPile"),
						ReplaceValue("allow_pinning_other", "All", "Vegvisir, Runestone, WildBeehive"),
						ReplaceValue("allow_pinning_dungeon", "All", "BurialChambers, TrollCave, SunkenCrypts, MountainCave, InfestedMine"),
						ReplaceValue("allow_pinning_spot", "All", "InfestedTree, FireHole, DrakeNest, GoblinCamp, TarPit, DvergrExcavation, DvergrGuardTower, DvergrHarbour, DvergrLighthouse, PetrifiedBone")
					}
				},
				{
					"[automatic_processing]",
					new List<Operation> { RemoveConfig("r/^([\\w_]+)_product_count_of_suppress_processing") }
				}
			});
		}

		private static void MigrationFor145(List<string> lines)
		{
			Migration(lines, new Dictionary<string, List<Operation>> { 
			{
				"[automatic_processing]",
				new List<Operation> { ReplaceValue("r/^allow_processing_by", "All", "Craft, Refuel, Store") }
			} });
		}

		private static void Migration(List<string> lines, Dictionary<string, List<Operation>> operations)
		{
			string category = "";
			int begin = -1;
			int i;
			List<Operation> value;
			for (i = 0; i < lines.Count; i++)
			{
				string text = lines[i];
				if (text.StartsWith("#") || string.IsNullOrWhiteSpace(text) || !Regex.IsMatch(text, "^\\[[\\w\\d_]+\\]$"))
				{
					continue;
				}
				if (begin > 0 && operations.TryGetValue(category, out value))
				{
					value.RemoveAll((Operation x) => x(category, lines, begin, i));
				}
				category = text;
				begin = i;
			}
			if (operations.TryGetValue(category, out value))
			{
				value.RemoveAll((Operation x) => x(category, lines, begin, i));
			}
			foreach (KeyValuePair<string, List<Operation>> item in operations.Where((KeyValuePair<string, List<Operation>> pair) => pair.Value.Any()))
			{
				Automatics.Logger.Warning($"{item.Value.Count} migrations for {item.Key} were not performed.");
			}
			ConfigCache.Clear();
		}

		private static Version ParseVersion(string line)
		{
			Match match = VersionPattern.Match(line);
			if (!match.Success)
			{
				Automatics.Logger.Error("Invalid version string: " + line);
				return new Version(0, 0, 0);
			}
			return new Version(int.Parse(match.Groups[1].Value), int.Parse(match.Groups[2].Value), int.Parse(match.Groups[3].Value));
		}
	}
	internal static class Hooks
	{
		public static Action<Player, ZNetView> OnPlayerAwake { get; set; }

		public static Action<Player, bool> OnPlayerUpdate { get; set; }

		public static Action<Player, float> OnPlayerFixedUpdate { get; set; }

		public static Action OnInitTerminal { get; set; }
	}
	[DisallowMultipleComponent]
	internal sealed class ContainerCache : InstanceCache<Container>
	{
	}
	[DisallowMultipleComponent]
	internal sealed class PickableCache : InstanceCache<Pickable>
	{
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(Player), "Awake")]
		[HarmonyPostfix]
		private static void Player_Awake_Postfix(Player __instance)
		{
			if (Objects.GetZNetView((Component)(object)__instance, out var zNetView))
			{
				Hooks.OnPlayerAwake?.Invoke(__instance, zNetView);
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Player_Update_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			Label label = default(Label);
			Label label2 = default(Label);
			return new CodeMatcher(instructions, generator).MatchEndForward((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdatePlacement", (Type[])null, (Type[])null), (string)null)
			}).Advance(1).CreateLabel(ref label)
				.Insert((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Ldloc_1, (object)null),
					new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(Action<Player, bool>), "Invoke", (Type[])null, (Type[])null))
				})
				.CreateLabel(ref label2)
				.MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null)
				})
				.Insert((CodeInstruction[])(object)new CodeInstruction[5]
				{
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Hooks), "get_OnPlayerUpdate", (Type[])null, (Type[])null)),
					new CodeInstruction(OpCodes.Dup, (object)null),
					new CodeInstruction(OpCodes.Brtrue_S, (object)label2),
					new CodeInstruction(OpCodes.Pop, (object)null),
					new CodeInstruction(OpCodes.Br_S, (object)label)
				})
				.InstructionEnumeration();
		}

		[HarmonyPatch(typeof(Player), "FixedUpdate")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Player_FixedUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			Label label = default(Label);
			Label label2 = default(Label);
			return new CodeMatcher(instructions, generator).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Player), "UpdateStealth", (Type[])null, (Type[])null), (string)null)
			}).Advance(1).CreateLabel(ref label)
				.Insert((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Ldloc_0, (object)null),
					new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(Action<Player, float>), "Invoke", (Type[])null, (Type[])null))
				})
				.CreateLabel(ref label2)
				.MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null)
				})
				.Insert((CodeInstruction[])(object)new CodeInstruction[5]
				{
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Hooks), "get_OnPlayerFixedUpdate", (Type[])null, (Type[])null)),
					new CodeInstruction(OpCodes.Dup, (object)null),
					new CodeInstruction(OpCodes.Brtrue_S, (object)label2),
					new CodeInstruction(OpCodes.Pop, (object)null),
					new CodeInstruction(OpCodes.Br_S, (object)label)
				})
				.InstructionEnumeration();
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		[HarmonyPrefix]
		private static void Terminal_InitTerminal_Prefix(out bool __state, bool ___m_terminalInitialized)
		{
			__state = ___m_terminalInitialized;
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		[HarmonyPostfix]
		private static void Terminal_InitTerminal_Postfix(bool __state)
		{
			if (!__state)
			{
				Hooks.OnInitTerminal?.Invoke();
			}
		}

		[HarmonyPatch(typeof(Container), "Awake")]
		[HarmonyPostfix]
		private static void Container_Awake_Postfix(Container __instance, ZNetView ___m_nview)
		{
			if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null)
			{
				((Component)__instance).gameObject.AddComponent<ContainerCache>();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Pickable), "Awake")]
		private static void Pickable_Awake_Postfix(Pickable __instance, ZNetView ___m_nview)
		{
			if (Object.op_Implicit((Object)(object)___m_nview) && ___m_nview.GetZDO() != null)
			{
				((Component)__instance).gameObject.AddComponent<PickableCache>();
			}
		}
	}
}
namespace Automatics.Valheim
{
	[Serializable]
	internal class ObjectMatcher
	{
		[NonSerialized]
		private bool _regex;

		[NonSerialized]
		private string _value;

		[NonSerialized]
		private Regex _pattern;

		public bool regex
		{
			get
			{
				return _regex;
			}
			set
			{
				_regex = value;
				OnUpdate();
			}
		}

		public string value
		{
			get
			{
				return _value;
			}
			set
			{
				_value = value;
				OnUpdate();
			}
		}

		public bool Matches(string name)
		{
			if (!regex || _pattern == null)
			{
				return string.Equals(name, _value, StringComparison.OrdinalIgnoreCase);
			}
			return _pattern.IsMatch(name);
		}

		private void OnUpdate()
		{
			_pattern = null;
			if (_regex && !string.IsNullOrEmpty(_value))
			{
				_pattern = new Regex(_value);
			}
		}
	}
	[Serializable]
	internal class ObjectElement
	{
		public string identifier { get; set; }

		public string label { get; set; }

		public List<ObjectMatcher> matches { get; set; }

		public bool IsValid()
		{
			if (!string.IsNullOrEmpty(identifier) && !string.IsNullOrEmpty(label))
			{
				return matches != null;
			}
			return false;
		}
	}
	[Serializable]
	internal class ObjectDataJson
	{
		public string type { get; set; }

		public int order { get; set; }

		public List<ObjectElement> values { get; set; }

		public bool IsValid()
		{
			if (!string.IsNullOrEmpty(type) && values != null)
			{
				return values.All((ObjectElement x) => x.IsValid());
			}
			return false;
		}
	}
	internal static class ObjectElementList
	{
		private static bool _initialized;

		private static string EscapeForToml(string json)
		{
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			char[] array = json.ToCharArray();
			foreach (char c in array)
			{
				switch (c)
				{
				case '\\':
					flag = true;
					stringBuilder.Append("$$");
					continue;
				case '"':
					if (!flag)
					{
						stringBuilder.Append('\\');
					}
					flag = false;
					break;
				default:
					flag = false;
					break;
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		private static string UnescapeToml(string toml)
		{
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			char[] array = toml.ToCharArray();
			foreach (char c in array)
			{
				switch (c)
				{
				case '\\':
					if (flag)
					{
						stringBuilder.Append('$');
					}
					flag = false;
					continue;
				case '$':
					if (flag)
					{
						stringBuilder.Append('\\');
					}
					flag = !flag;
					continue;
				}
				if (flag)
				{
					stringBuilder.Append('$');
				}
				flag = false;
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		private static Action<ConfigEntryBase> GetCustomDrawer()
		{
			string identifierInput = "";
			string labelInput = "";
			string valueInput = "";
			return delegate(ConfigEntryBase entry)
			{
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Expected O, but got Unknown
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Expected O, but got Unknown
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Expected O, but got Unknown
				//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Expected O, but got Unknown
				//IL_0375: Unknown result type (might be due to invalid IL or missing references)
				//IL_037f: Expected O, but got Unknown
				//IL_037a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0394: Unknown result type (might be due to invalid IL or missing references)
				//IL_039e: Expected O, but got Unknown
				//IL_0399: Unknown result type (might be due to invalid IL or missing references)
				//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0415: Expected O, but got Unknown
				int num = Mathf.Min(Screen.width, 650);
				int num2 = num - Mathf.RoundToInt((float)num / 2.5f) - 115;
				string text = Automatics.L10N.Translate("mod_utils_config_button_add");
				string text2 = Automatics.L10N.Translate("mod_utils_config_button_remove");
				string text3 = Automatics.L10N.Translate("@config_object_element_identifier");
				string text4 = Automatics.L10N.Translate("@config_object_element_label");
				string text5 = Automatics.L10N.Translate("@config_object_element_value");
				float num3 = Mathf.Max(new float[3]
				{
					GUI.skin.label.CalcSize(new GUIContent(text3)).x,
					GUI.skin.label.CalcSize(new GUIContent(text4)).x,
					GUI.skin.label.CalcSize(new GUIContent(text5)).x
				});
				List<ObjectElement> list = new List<ObjectElement>((List<ObjectElement>)entry.BoxedValue);
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth((float)num2) });
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(new GUIContent(text3, ""), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num3) });
				identifierInput = GUILayout.TextField(string.Concat(identifierInput.Where((char x) => !char.IsWhiteSpace(x))), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(text4, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num3) });
				labelInput = GUILayout.TextField(labelInput, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(text5, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num3) });
				valueInput = GUILayout.TextField(valueInput, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }) && !string.IsNullOrEmpty(identifierInput) && !string.IsNullOrEmpty(labelInput) && !string.IsNullOrEmpty(valueInput))
				{
					bool flag = valueInput.StartsWith("r/");
					valueInput = (flag ? valueInput.Substring(2) : valueInput);
					list.Add(new ObjectElement
					{
						identifier = identifierInput,
						label = labelInput,
						matches = new List<ObjectMatcher>
						{
							new ObjectMatcher
							{
								regex = flag,
								value = valueInput
							}
						}
					});
					entry.BoxedValue = list;
					identifierInput = "";
					labelInput = "";
					valueInput = "";
				}
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				double num4 = 0.0;
				foreach (ObjectElement item in list.ToList())
				{
					string identifier = item.identifier;
					string label = item.label;
					string text6 = Automatics.L10N.TranslateInternalName(label);
					string value = item.matches[0].value;
					int num5 = Mathf.FloorToInt(GUI.skin.label.CalcSize(new GUIContent(text6)).x) + Mathf.FloorToInt(GUI.skin.button.CalcSize(new GUIContent(text2)).x);
					num4 += (double)num5;
					if (num4 > (double)num2)
					{
						GUILayout.EndHorizontal();
						num4 = num5;
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					}
					string text7 = Automatics.L10N.LocalizeTextOnly("@config_object_element_preview", text6, label, identifier, value);
					GUILayout.Label(new GUIContent(text6, text7), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
					if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }) && list.Remove(item))
					{
						entry.BoxedValue = list;
					}
				}
				GUILayout.EndHorizontal();
				GUILayout.EndVertical();
				GUILayout.FlexibleSpace();
			};
		}

		public static void Initialize()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			if (!_initialized)
			{
				_initialized = true;
				TomlTypeConverter.AddConverter(typeof(List<ObjectElement>), new TypeConverter
				{
					ConvertToObject = (string str, Type type) => (!string.IsNullOrEmpty(str)) ? Json.Parse<List<ObjectElement>>(UnescapeToml(str.Trim(new char[1] { '"' }))) : new List<ObjectElement>(),
					ConvertToString = delegate(object obj, Type type)
					{
						List<ObjectElement> list = (List<ObjectElement>)obj;
						return (!list.Any()) ? "" : ("\"" + EscapeForToml(Json.ToString(list)) + "\"");
					}
				});
				ConfigurationCustomDrawer.Register((Type type, AcceptableValueBase value) => type == typeof(List<ObjectElement>), GetCustomDrawer);
			}
		}
	}
	internal class ValheimObject
	{
		private static readonly List<ObjectDataJson> JsonCache;

		public static readonly ValheimObject Animal;

		public static readonly ValheimObject Dungeon;

		public static readonly ValheimObject Flora;

		public static readonly ValheimObject Mineral;

		public static readonly ValheimObject Monster;

		public static readonly ValheimObject Spawner;

		public static readonly ValheimObject Spot;

		private readonly string _type;

		private readonly Dictionary<string, ObjectElement> _elements;

		private readonly Dictionary<string, ObjectElement> _customElements;

		private readonly List<ObjectElement> _allElements;

		static ValheimObject()
		{
			JsonCache = new List<ObjectDataJson>();
			Animal = new ValheimObject("animal");
			Dungeon = new ValheimObject("dungeon");
			Flora = new ValheimObject("flora");
			Mineral = new ValheimObject("mineral");
			Monster = new ValheimObject("monster");
			Spawner = new ValheimObject("spawner");
			Spot = new ValheimObject("spot");
			ObjectElementList.Initialize();
		}

		public ValheimObject(string type)
		{
			_type = type;
			_elements = new Dictionary<string, ObjectElement>();
			_customElements = new Dictionary<string, ObjectElement>();
			_allElements = new List<ObjectElement>();
			if (JsonCache.Any())
			{
				Register(JsonCache);
			}
		}

		private static void Initialize(string directory)
		{
			if (!Directory.Exists(directory))
			{
				Automatics.Logger.Debug("Directory does not exist: " + directory);
				return;
			}
			JsonCache.AddRange(from x in Directory.EnumerateFiles(directory, "*.json", SearchOption.AllDirectories).Select(delegate(string x)
				{
					try
					{
						return Json.Parse<ObjectDataJson>(File.ReadAllText(x));
					}
					catch (Exception arg)
					{
						Automatics.Logger.Error($"Failed to read Json file\n{arg}");
						return new ObjectDataJson();
					}
				})
				where x.IsValid()
				select x);
		}

		public static void Initialize(IEnumerable<string> directories)
		{
			foreach (string directory in directories)
			{
				Initialize(directory);
			}
			Animal.Register(JsonCache);
			Dungeon.Register(JsonCache);
			Flora.Register(JsonCache);
			Mineral.Register(JsonCache);
			Monster.Register(JsonCache);
			Spawner.Register(JsonCache);
			Spot.Register(JsonCache);
		}

		public static void PostInitialize()
		{
			JsonCache.Clear();
		}

		private void UpdateElements()
		{
			_allElements.Clear();
			_allElements.AddRange(_elements.Values);
			_allElements.AddRange(_customElements.Values);
		}

		private void Register(IEnumerable<ObjectDataJson> jsons)
		{
			foreach (ObjectElement item in (from x in jsons
				where x.type.ToLower() == _type
				orderby x.order
				select x).SelectMany((ObjectDataJson x) => x.values))
			{
				_elements[item.identifier.ToLower()] = new ObjectElement
				{
					identifier = item.identifier,
					label = item.label,
					matches = new List<ObjectMatcher>(item.matches)
				};
			}
			UpdateElements();
		}

		public void RegisterCustom(IEnumerable<ObjectElement> elements)
		{
			_customElements.Clear();
			foreach (ObjectElement element in elements)
			{
				_customElements[element.identifier.ToLower()] = new ObjectElement
				{
					identifier = element.identifier,
					label = element.label,
					matches = new List<ObjectMatcher>(element.matches)
				};
			}
			UpdateElements();
		}

		public IEnumerable<ObjectElement> GetElements()
		{
			return new List<ObjectElement>(_elements.Values);
		}

		public IEnumerable<ObjectElement> GetCustomElements()
		{
			return new List<ObjectElement>(_customElements.Values);
		}

		public IEnumerable<ObjectElement> GetAllElements()
		{
			return _allElements.ToList();
		}

		public bool GetIdentify(string name, out string identifier)
		{
			ObjectElement objectElement = _allElements.FirstOrDefault((ObjectElement x) => x.matches.All((ObjectMatcher y) => y.Matches(name)));
			if (objectElement == null || !objectElement.IsValid())
			{
				identifier = "";
				return false;
			}
			identifier = objectElement.identifier;
			return true;
		}

		public bool GetName(string identifier, out string name)
		{
			string key = identifier.ToLower();
			if (!_elements.TryGetValue(key, out var value) && !_customElements.TryGetValue(key, out value))
			{
				name = "";
				return false;
			}
			name = value.label;
			return true;
		}

		public bool IsDefined(string nameOrIdentify)
		{
			if (!GetIdentify(nameOrIdentify, out var identifier))
			{
				return GetName(nameOrIdentify, out identifier);
			}
			return true;
		}
	}
}
namespace Automatics.ConsoleCommands
{
	internal abstract class Command
	{
		private static readonly Dictionary<string, Command> Commands;

		private static readonly List<string> EmptyList;

		private readonly Lazy<OptionSet> _optionsLazy;

		protected readonly string command;

		protected List<string> extraOptions;

		private bool _showHelp;

		protected OptionSet options => _optionsLazy.Value;

		protected bool HaveExtraOption { get; set; }

		protected bool HaveExtraDescription { get; set; }

		static Command()
		{
			Commands = new Dictionary<string, Command>();
			EmptyList = new List<string>();
		}

		protected Command(string command)
		{
			this.command = command.ToLower();
			_optionsLazy = new Lazy<OptionSet>(delegate
			{
				OptionSet optionSet = CreateOptionSet();
				optionSet.Add("h|help", Automatics.L10N.Translate("@command_common_help_description"), delegate(string v)
				{
					_showHelp = v != null;
				});
				return optionSet;
			});
			extraOptions = new List<string>();
		}

		private static IEnumerable<string> ParseArgs(string line)
		{
			List<string> list = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			bool flag2 = false;
			foreach (char c in line)
			{
				switch (c)
				{
				case '\\':
					if (!flag2)
					{
						flag2 = true;
						continue;
					}
					break;
				case '"':
					if (!flag2)
					{
						flag = !flag;
						continue;
					}
					break;
				case ' ':
					if (!flag)
					{
						list.Add(stringBuilder.ToString());
						stringBuilder.Clear();
						flag2 = false;
						continue;
					}
					break;
				}
				stringBuilder.Append(c);
				flag2 = false;
			}
			if (stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
			}
			return list.Skip(1).ToList();
		}

		protected static IEnumerable<(string Command, Command Instance)> GetAllCommands()
		{
			return Commands.Select((KeyValuePair<string, Command> x) => (x.Key, x.Value));
		}

		[Conditional("DEBUG")]
		private void DebugLog()
		{
			Automatics.Logger.Debug("[COMMAND]: ### " + command);
			string[] array = Help().Split(new char[1] { '\n' }, StringSplitOptions.None);
			foreach (string text in array)
			{
				Automatics.Logger.Debug("[COMMAND]: " + text.Trim());
			}
		}

		protected abstract void CommandAction(ConsoleEventArgs args);

		protected virtual OptionSet CreateOptionSet()
		{
			return new OptionSet();
		}

		protected virtual List<string> GetSuggestions()
		{
			return EmptyList;
		}

		protected virtual void ResetOptions()
		{
			_showHelp = false;
		}

		protected bool ParseArgs(ConsoleEventArgs args)
		{
			ResetOptions();
			try
			{
				extraOptions = options.Parse(ParseArgs(args.FullLine));
			}
			catch (OptionException ex)
			{
				args.Context.AddString(command + ":");
				args.Context.AddString(ex.Message);
				args.Context.AddString(Automatics.L10N.LocalizeTextOnly("@command_common_option_parse_error", command));
				return false;
			}
			if (!_showHelp)
			{
				return true;
			}
			args.Context.AddString(Help());
			return false;
		}

		protected string Usage()
		{
			return Automatics.L10N.Translate("@command_" + command + "_usage");
		}

		protected string Description()
		{
			return Automatics.L10N.Translate("@command_" + command + "_description");
		}

		protected string ExtraOption()
		{
			return Automatics.L10N.Translate("@command_" + command + "_extra_option");
		}

		protected string ExtraDescription()
		{
			return Automatics.L10N.Translate("@command_" + command + "_extra_description");
		}

		protected string Help()
		{
			StringWriter stringWriter = new StringWriter();
			stringWriter.WriteLine(Usage());
			stringWriter.WriteLine(Description());
			if (HaveExtraOption)
			{
				stringWriter.WriteLine();
				stringWriter.WriteLine(ExtraOption());
			}
			stringWriter.WriteLine();
			stringWriter.WriteLine(Automatics.L10N.Translate("@command_common_help_options_label"));
			options.WriteOptionDescriptions(stringWriter);
			if (HaveExtraDescription)
			{
				stringWriter.WriteLine();
				stringWriter.WriteLine(ExtraDescription());
			}
			return stringWriter.ToString();
		}

		public string Print(bool verbose)
		{
			if (verbose)
			{
				return Help();
			}
			return "\"" + command + "\" " + Description();
		}

		public void Register(bool isCheat = false, bool isNetwork = false, bool onlyServer = false, bool isSecret = false, bool allowInDevBuild = false)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0046: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Commands[command] = this;
			new ConsoleCommand(command, Description(), new ConsoleEvent(CommandAction), isCheat, isNetwork, onlyServer, isSecret, allowInDevBuild, new ConsoleOptionsFetcher(GetSuggestions), false, false, false);
		}
	}
	internal class PrintNames : Command
	{
		public PrintNames()
			: base("printnames")
		{
			base.HaveExtraOption = true;
			base.HaveExtraDescription = true;
		}

		protected override void CommandAction(ConsoleEventArgs args)
		{
			if (!ParseArgs(args))
			{
				return;
			}
			Automatics.Logger.Message(() => "Command exec: " + args.FullLine);
			List<(bool Regex, string Value)> filters = extraOptions.Select((string arg) => (!arg.StartsWith("r/", StringComparison.OrdinalIgnoreCase)) ? (false, arg) : (true, arg.Substring(2))).ToList();
			foreach (var item3 in from <>h__TransparentIdentifier0 in GetAllTranslations().Select(delegate(KeyValuePair<string, string> translation)
				{
					KeyValuePair<string, string> keyValuePair = translation;
					string key;
					if (!keyValuePair.Key.StartsWith("automatics_"))
					{
						keyValuePair = translation;
						key = "$" + keyValuePair.Key;
					}
					else
					{
						keyValuePair = translation;
						key = "@" + keyValuePair.Key.Substring(11);
					}
					return new { translation, key };
				})
				let value = translation.Value
				where filters.All(delegate((bool Regex, string Value) filter)
				{
					if (!filter.Regex)
					{
						if (key.IndexOf(filter.Value, StringComparison.OrdinalIgnoreCase) < 0)
						{
							return value.IndexOf(filter.Value, StringComparison.OrdinalIgnoreCase) >= 0;
						}
						return true;
					}
					return Regex.IsMatch(key, filter.Value) || Regex.IsMatch(value, filter.Value);
				})
				select (key, value))
			{
				string item = item3.Item1;
				string item2 = item3.Item2;
				string text = Automatics.L10N.LocalizeTextOnly("@command_printnames_result_format", item, item2);
				args.Context.AddString(text);
				Automatics.Logger.Message(() => "  " + text);
			}
			args.Context.AddString("");
			static Dictionary<string, string> GetAllTranslations()
			{
				return Reflections.GetField<Dictionary<string, string>>(Localization.instance, "m_translations");
			}
		}
	}
	internal class PrintObjects : Command
	{
		private static readonly Collider[] ColliderBuffer;

		private int _radius;

		private int _number;

		private string _include;

		private string _exclude;

		static PrintObjects()
		{
			ColliderBuffer = (Collider[])(object)new Collider[4096];
		}

		public PrintObjects()
			: base("printobjects")
		{
			base.HaveExtraOption = true;
			base.HaveExtraDescription = true;
		}

		private static (bool IsValid, bool IsRegex, string Value) CreateFilter(string arg)
		{
			if (string.IsNullOrEmpty(arg))
			{
				return (false, false, "");
			}
			if (!arg.StartsWith("r/", StringComparison.OrdinalIgnoreCase))
			{
				return (true, false, arg);
			}
			return (true, true, arg.Substring(2));
		}

		private static boo