Decompiled source of MacaronCore v1.1.0

plugins/MacaronCore/MacaronCore.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon;
using Pigeon.Movement;
using Pigeon.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MacaronCore")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+fe8cef1291afd0a7f7ea8a9ddfd28d3607c4cdd5")]
[assembly: AssemblyProduct("MacaronCore")]
[assembly: AssemblyTitle("MacaronCore")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MycopunkShared
{
	[BepInPlugin("doku_macaron.mycopunk.macaroncore", "Macaron Core", "1.1.0")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class MacaronCorePlugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("doku_macaron.mycopunk.macaroncore");
			ModsMenu.Install(_harmony, (BaseUnityPlugin)(object)this);
			Hotkeys.ReportConflicts((BaseUnityPlugin)(object)this);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Macaron Core 1.1.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class Hotkeys
	{
		private sealed class Binding
		{
			public string Guid;

			public string Owner;

			public Key Key;

			public string Modifiers;

			public bool FromConfig;

			public string KeyText
			{
				get
				{
					if (Modifiers.Length != 0)
					{
						return Modifiers + "+" + ((object)Unsafe.As<Key, Key>(ref Key)/*cast due to .constrained prefix*/).ToString();
					}
					return ((object)Unsafe.As<Key, Key>(ref Key)/*cast due to .constrained prefix*/).ToString();
				}
			}
		}

		private const string RegistryKey = "MycopunkShared.Hotkeys.v1.registry";

		private const string ReporterKey = "MycopunkShared.Hotkeys.v1.reporter";

		private const float GameInputTimeout = 120f;

		public unsafe static void Register(BaseUnityPlugin plugin, Key key, string purpose)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key == 0)
			{
				return;
			}
			try
			{
				BepInPlugin metadata = plugin.Info.Metadata;
				string item = string.Join("\t", metadata.GUID, metadata.Name, ((object)(*(Key*)(&key))/*cast due to .constrained prefix*/).ToString(), "", purpose ?? "");
				if (!Registry().Contains(item))
				{
					Registry().Add(item);
				}
			}
			catch
			{
			}
		}

		public static void ReportConflicts(BaseUnityPlugin host)
		{
			try
			{
				AppDomain currentDomain = AppDomain.CurrentDomain;
				if (currentDomain.GetData("MycopunkShared.Hotkeys.v1.reporter") == null)
				{
					currentDomain.SetData("MycopunkShared.Hotkeys.v1.reporter", host.Info.Metadata.GUID);
					((MonoBehaviour)host).StartCoroutine(ReportWhenReady());
				}
			}
			catch
			{
			}
		}

		private static List<string> Registry()
		{
			AppDomain currentDomain = AppDomain.CurrentDomain;
			List<string> list = currentDomain.GetData("MycopunkShared.Hotkeys.v1.registry") as List<string>;
			if (list == null)
			{
				list = new List<string>();
				currentDomain.SetData("MycopunkShared.Hotkeys.v1.registry", list);
			}
			return list;
		}

		private static IEnumerator ReportWhenReady()
		{
			yield return null;
			float start = Time.realtimeSinceStartup;
			while (PlayerInput._controls == null && Time.realtimeSinceStartup - start < 120f)
			{
				yield return (object)new WaitForSecondsRealtime(1f);
			}
			ManualLogSource val = Logger.CreateLogSource("Hotkeys");
			try
			{
				Report(val, PlayerInput._controls);
			}
			catch (Exception ex)
			{
				val.LogWarning((object)("Hotkey check failed: " + ex));
			}
		}

		private static void Report(ManualLogSource log, PlayerControls controls)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			List<Binding> list = new List<Binding>();
			foreach (string item in Registry())
			{
				string[] array = item.Split('\t');
				if (array.Length >= 5 && Enum.TryParse<Key>(array[2], out Key result))
				{
					list.Add(new Binding
					{
						Guid = array[0],
						Owner = array[1] + ((array[4].Length > 0) ? (" (" + array[4] + ")") : ""),
						Key = result,
						Modifiers = array[3]
					});
				}
			}
			AddConfigEntries(list);
			string note;
			List<Binding> list2 = GameBindings(controls, out note);
			int count = list2.Count;
			IEnumerable<string> values = from b in list
				orderby ((object)Unsafe.As<Key, Key>(ref b.Key)/*cast due to .constrained prefix*/).ToString()
				select b.KeyText + " " + b.Owner;
			log.LogInfo((object)("Mod hotkeys: " + ((list.Count == 0) ? "none" : string.Join(", ", values)) + ". Game keyboard bindings checked: " + count + note + "."));
			int num = 0;
			foreach (IGrouping<Key, Binding> item2 in from b in list.Concat(list2)
				group b by b.Key)
			{
				List<Binding> list3 = item2.ToList();
				if (!list3.Any((Binding b) => b.Guid != null))
				{
					continue;
				}
				List<Binding> list4 = new List<Binding>();
				for (int num2 = 0; num2 < list3.Count; num2++)
				{
					for (int num3 = num2 + 1; num3 < list3.Count; num3++)
					{
						if (Clash(list3[num2], list3[num3]))
						{
							if (!list4.Contains(list3[num2]))
							{
								list4.Add(list3[num2]);
							}
							if (!list4.Contains(list3[num3]))
							{
								list4.Add(list3[num3]);
							}
						}
					}
				}
				if (list4.Count != 0)
				{
					num++;
					log.LogWarning((object)("Hotkey conflict on " + ((object)item2.Key/*cast due to .constrained prefix*/).ToString() + ": " + string.Join(", ", list4.Select((Binding b) => ((b.Modifiers.Length > 0) ? ("[" + b.KeyText + "] ") : "") + b.Owner))));
				}
			}
			if (num == 0)
			{
				log.LogInfo((object)"No hotkey conflicts found.");
			}
		}

		private static bool Clash(Binding a, Binding b)
		{
			if (a.Guid == null && b.Guid == null)
			{
				return false;
			}
			if (a.Guid != null && a.Guid == b.Guid && a.Owner == b.Owner)
			{
				return false;
			}
			if (a.Modifiers.Length != 0 && b.Modifiers.Length != 0)
			{
				return a.Modifiers == b.Modifiers;
			}
			return true;
		}

		private unsafe static void AddConfigEntries(List<Binding> into)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
			{
				ConfigFile val;
				try
				{
					val = (((Object)(object)value2.Instance != (Object)null) ? value2.Instance.Config : null);
				}
				catch
				{
					continue;
				}
				if (val == null)
				{
					continue;
				}
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in val)
				{
					ConfigEntryBase value = item.Value;
					Key key = (Key)0;
					string modifiers = "";
					object boxedValue = value.BoxedValue;
					if (boxedValue is Key val2)
					{
						key = val2;
					}
					else if (boxedValue is KeyCode code)
					{
						key = FromKeyCode(code);
					}
					else if (boxedValue is KeyboardShortcut val3)
					{
						key = FromKeyCode(((KeyboardShortcut)(ref val3)).MainKey);
						modifiers = string.Join("+", (from m in ((KeyboardShortcut)(ref val3)).Modifiers.Select(FromKeyCode)
							where (int)m > 0
							select ((object)(*(Key*)(&m))/*cast due to .constrained prefix*/).ToString()).OrderBy<string, string>((string s) => s, StringComparer.Ordinal));
					}
					if ((int)key != 0)
					{
						string guid = value2.Metadata.GUID;
						if (!into.Any((Binding b) => b.Guid == guid && b.Key == key && b.Modifiers == modifiers))
						{
							into.Add(new Binding
							{
								Guid = guid,
								Owner = value2.Metadata.Name + " [" + item.Key.Section + "." + item.Key.Key + "]",
								Key = key,
								Modifiers = modifiers,
								FromConfig = true
							});
						}
					}
				}
			}
		}

		private static List<Binding> GameBindings(PlayerControls controls, out string note)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			List<Binding> list = new List<Binding>();
			note = "";
			Keyboard current = Keyboard.current;
			if (controls == null)
			{
				note = " (the game's input was not created yet)";
				return list;
			}
			if (current == null)
			{
				note = " (no keyboard)";
				return list;
			}
			InputActionAsset asset = controls.asset;
			if ((Object)(object)asset == (Object)null)
			{
				note = " (PlayerControls.asset not found)";
				return list;
			}
			Enumerator<InputActionMap> enumerator = asset.actionMaps.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputActionMap current2 = enumerator.Current;
					Enumerator<InputAction> enumerator2 = current2.actions.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							InputAction current3 = enumerator2.Current;
							Enumerator<InputBinding> enumerator3 = current3.bindings.GetEnumerator();
							try
							{
								while (enumerator3.MoveNext())
								{
									InputBinding current4 = enumerator3.Current;
									string effectivePath = ((InputBinding)(ref current4)).effectivePath;
									if (((InputBinding)(ref current4)).isComposite || string.IsNullOrEmpty(effectivePath) || !effectivePath.StartsWith("<Keyboard>", StringComparison.OrdinalIgnoreCase))
									{
										continue;
									}
									InputControl val = InputControlPath.TryFindControl((InputControl)(object)current, effectivePath, 0);
									KeyControl control = (KeyControl)(object)((val is KeyControl) ? val : null);
									if (control != null)
									{
										string owner = "game " + current2.name + "/" + current3.name;
										if (!list.Any((Binding b) => b.Key == control.keyCode && b.Owner == owner))
										{
											list.Add(new Binding
											{
												Owner = owner,
												Key = control.keyCode,
												Modifiers = ""
											});
										}
									}
								}
							}
							finally
							{
								((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
					}
				}
				return list;
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static Key FromKeyCode(KeyCode code)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected I4, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected I4, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Invalid comparison between Unknown and I4
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			string text = ((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Alpha"))
			{
				text = "Digit" + text.Substring(5);
			}
			else if (text.StartsWith("Keypad"))
			{
				text = "Numpad" + text.Substring(6);
			}
			if ((int)code <= 96)
			{
				if ((int)code == 13)
				{
					return (Key)2;
				}
				if ((int)code == 96)
				{
					return (Key)4;
				}
			}
			else
			{
				switch (code - 266)
				{
				case 5:
					return (Key)77;
				case 4:
					return (Key)80;
				case 3:
					return (Key)81;
				case 2:
					return (Key)79;
				case 1:
					return (Key)78;
				case 0:
					return (Key)82;
				}
				switch (code - 305)
				{
				case 1:
					return (Key)55;
				case 0:
					return (Key)56;
				case 5:
				case 6:
					return (Key)57;
				case 4:
				case 7:
					return (Key)58;
				}
			}
			if (!Enum.TryParse<Key>(text, ignoreCase: true, out Key result))
			{
				return (Key)0;
			}
			return result;
		}
	}
	public static class HudVisibility
	{
		public static bool HealthBarVisible(Player player, Graphic bar, Canvas canvas)
		{
			if ((Object)(object)player != (Object)null && player.IsAlive && (Object)(object)bar != (Object)null && ((Behaviour)bar).isActiveAndEnabled && (Object)(object)canvas != (Object)null && ((Behaviour)canvas).isActiveAndEnabled)
			{
				return !ResultsOpen();
			}
			return false;
		}

		public static bool ResultsOpen()
		{
			GameManager instance = GameManager.Instance;
			WindowSystem val = (((Object)(object)instance != (Object)null) ? instance.WindowSystem : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			for (int i = 0; i < val.Count; i++)
			{
				if (val[i] is MissionRewardsWindow || val[i] is MissionStatsWindow)
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class GameHudText
	{
		public static TextMeshProUGUI Create(TextMeshProUGUI template, Transform parent, string name)
		{
			TextMeshProUGUI val = Object.Instantiate<TextMeshProUGUI>(template, parent, false);
			((Object)val).name = name;
			for (int num = ((TMP_Text)val).transform.childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)((TMP_Text)val).transform.GetChild(num)).gameObject);
			}
			((Graphic)val).raycastTarget = false;
			((TMP_Text)val).richText = false;
			((TMP_Text)val).enableAutoSizing = false;
			((TMP_Text)val).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val).overflowMode = (TextOverflowModes)0;
			return val;
		}

		public static void SetText(TextMeshProUGUI label, string text)
		{
			if (((TMP_Text)label).text != text)
			{
				((TMP_Text)label).text = text;
			}
		}

		public static void SetActive(TextMeshProUGUI label, bool active)
		{
			if (((Component)label).gameObject.activeSelf != active)
			{
				((Component)label).gameObject.SetActive(active);
			}
		}
	}
	public static class HudAnchor
	{
		public const float Unset = -1f;

		public static bool IsCustom(float x, float y)
		{
			if (x >= 0f)
			{
				return y >= 0f;
			}
			return false;
		}

		public static void Resolve(float x, float y, float defaultX, float defaultY, out float anchorX, out float anchorY)
		{
			if (IsCustom(x, y))
			{
				anchorX = ((x > 1f) ? 1f : x);
				anchorY = ((y > 1f) ? 1f : y);
			}
			else
			{
				anchorX = defaultX;
				anchorY = defaultY;
			}
		}
	}
	public static class HudCoordinates
	{
		public static Camera CameraFor(Canvas root)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)root.renderMode != 0)
			{
				if (!((Object)(object)root.worldCamera != (Object)null))
				{
					return Camera.main;
				}
				return root.worldCamera;
			}
			return null;
		}
	}
	public sealed class HudPlacement
	{
		private static class ModSettingsMenuBridge
		{
			private static bool _looked;

			private static MethodInfo _register;

			private static MethodInfo _unregister;

			private static void Find()
			{
				if (_looked)
				{
					return;
				}
				_looked = true;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					Type type;
					try
					{
						type = assembly.GetType("HudRepositionAPI", throwOnError: false);
					}
					catch
					{
						continue;
					}
					if (!(type == null))
					{
						_register = type.GetMethod("Register", BindingFlags.Static | BindingFlags.Public, null, new Type[5]
						{
							typeof(string),
							typeof(string),
							typeof(RectTransform),
							typeof(ConfigEntry<float>),
							typeof(ConfigEntry<float>)
						}, null);
						_unregister = type.GetMethod("Unregister", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
						break;
					}
				}
			}

			public static bool Register(string id, string name, RectTransform rect, ConfigEntry<float> x, ConfigEntry<float> y)
			{
				try
				{
					Find();
					if (_register == null)
					{
						return false;
					}
					_register.Invoke(null, new object[5] { id, name, rect, x, y });
					return true;
				}
				catch
				{
					return false;
				}
			}

			public static void Unregister(string id)
			{
				try
				{
					_unregister?.Invoke(null, new object[1] { id });
				}
				catch
				{
				}
			}
		}

		private readonly string _id;

		private readonly string _displayName;

		private RectTransform _element;

		private float _defaultX;

		private float _defaultY;

		private bool _registered;

		public ConfigEntry<float> AnchorX { get; }

		public ConfigEntry<float> AnchorY { get; }

		public bool IsCustom => HudAnchor.IsCustom(AnchorX.Value, AnchorY.Value);

		private HudPlacement(string id, string displayName, ConfigEntry<float> x, ConfigEntry<float> y)
		{
			_id = id;
			_displayName = displayName;
			AnchorX = x;
			AnchorY = y;
			x.SettingChanged += delegate
			{
				Apply();
			};
			y.SettingChanged += delegate
			{
				Apply();
			};
		}

		public static HudPlacement Bind(BaseUnityPlugin plugin, string name)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			string text = "HUD Position: " + name;
			ConfigEntry<float> x = plugin.Config.Bind<float>(text, "AnchorX", -1f, new ConfigDescription("Horizontal position as a fraction of the HUD area it belongs to (0 = left, 1 = right). Negative: the default position.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigEntry<float> y = plugin.Config.Bind<float>(text, "AnchorY", -1f, new ConfigDescription("Vertical position as a fraction of the HUD area it belongs to (0 = bottom, 1 = top). Negative: the default position.", (AcceptableValueBase)null, Array.Empty<object>()));
			return new HudPlacement(plugin.Info.Metadata.GUID + "/" + name, name, x, y);
		}

		public void Attach(RectTransform element, RectTransform parent, Vector2 defaultAnchor)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)element == (Object)null) && !((Object)(object)parent == (Object)null))
			{
				if ((Object)(object)((Transform)element).parent != (Object)(object)parent)
				{
					((Transform)element).SetParent((Transform)(object)parent, false);
				}
				_element = element;
				_defaultX = defaultAnchor.x;
				_defaultY = defaultAnchor.y;
				Apply();
				Register();
			}
		}

		public void SetDefault(Vector2 defaultAnchor)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (!Mathf.Approximately(_defaultX, defaultAnchor.x) || !Mathf.Approximately(_defaultY, defaultAnchor.y))
			{
				_defaultX = defaultAnchor.x;
				_defaultY = defaultAnchor.y;
				if (!IsCustom)
				{
					Apply();
				}
			}
		}

		public void Reset()
		{
			AnchorX.Value = -1f;
			AnchorY.Value = -1f;
		}

		public void Detach()
		{
			if (_registered)
			{
				ModSettingsMenuBridge.Unregister(_id);
			}
			_registered = false;
			_element = null;
		}

		private void Apply()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_element == (Object)null))
			{
				HudAnchor.Resolve(AnchorX.Value, AnchorY.Value, _defaultX, _defaultY, out var anchorX, out var anchorY);
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(anchorX, anchorY);
				_element.anchorMin = val;
				_element.anchorMax = val;
				_element.anchoredPosition = Vector2.zero;
			}
		}

		private void Register()
		{
			if (_registered)
			{
				ModSettingsMenuBridge.Unregister(_id);
			}
			_registered = ModSettingsMenuBridge.Register(_id, _displayName, _element, AnchorX, AnchorY);
		}
	}
	public interface IHudLine
	{
		string Name { get; set; }
	}
	public interface ITeammateHud
	{
		float NameFontSize { get; }

		bool HasPrevious { get; }

		float Offset { get; set; }

		string Marker { get; set; }

		IEnumerable<IHudLine> Siblings { get; }

		IHudLine CreateLine(string name);

		void DestroyLine(IHudLine line);

		void MoveLower(float dy);

		void MoveRoot(float dy);

		void PlaceLine(IHudLine line, float below);
	}
	public static class TeammateHudLines
	{
		private struct State
		{
			public float Lower;

			public float Offset;

			public float LineHeight;
		}

		public const string LinePrefix = "MycoLine|";

		public const string MarkerPrefix = "MycoHudLines|";

		public const string RemovedName = "MycoLine (removed)";

		public static IHudLine Add(ITeammateHud hud, string id, int order)
		{
			IHudLine hudLine = Find(hud, id);
			if (hudLine == null)
			{
				hudLine = hud.CreateLine("MycoLine|" + order.ToString("D4", CultureInfo.InvariantCulture) + "|" + id);
			}
			Layout(hud);
			return hudLine;
		}

		public static void Remove(ITeammateHud hud, string id)
		{
			IHudLine hudLine = Find(hud, id);
			if (hudLine != null)
			{
				hudLine.Name = "MycoLine (removed)";
				hud.DestroyLine(hudLine);
				Layout(hud);
			}
		}

		public static void Place(ITeammateHud hud)
		{
			if (TryParse(hud.Marker, out var state))
			{
				PlaceLines(hud, Lines(hud), state.LineHeight);
			}
		}

		public static List<T> TopLevel<T>(IList<T> candidates, T name, Func<T, T, bool> isInside) where T : class
		{
			List<T> list = new List<T>();
			foreach (T candidate in candidates)
			{
				if (candidate == null || candidate == name || isInside(name, candidate) || list.Contains(candidate))
				{
					continue;
				}
				bool flag = false;
				foreach (T candidate2 in candidates)
				{
					if (candidate2 != null && candidate2 != candidate && candidate2 != name && !isInside(name, candidate2) && isInside(candidate, candidate2))
					{
						flag = true;
					}
				}
				if (!flag)
				{
					list.Add(candidate);
				}
			}
			return list;
		}

		public static float LineHeight(float nameFontSize)
		{
			return Math.Max(nameFontSize * 1.15f, 18f);
		}

		private static IHudLine Find(ITeammateHud hud, string id)
		{
			foreach (IHudLine item in Lines(hud))
			{
				if (item.Name.EndsWith("|" + id, StringComparison.Ordinal))
				{
					return item;
				}
			}
			return null;
		}

		private static List<IHudLine> Lines(ITeammateHud hud)
		{
			List<IHudLine> list = new List<IHudLine>();
			foreach (IHudLine sibling in hud.Siblings)
			{
				if (sibling != null && sibling.Name != null && sibling.Name.StartsWith("MycoLine|", StringComparison.Ordinal))
				{
					list.Add(sibling);
				}
			}
			list.Sort((IHudLine a, IHudLine b) => string.CompareOrdinal(a.Name, b.Name));
			return list;
		}

		private static void PlaceLines(ITeammateHud hud, List<IHudLine> lines, float lineHeight)
		{
			for (int i = 0; i < lines.Count; i++)
			{
				hud.PlaceLine(lines[i], (float)(i + 1) * lineHeight);
			}
		}

		private static void Layout(ITeammateHud hud)
		{
			TryParse(hud.Marker, out var state);
			float offset = hud.Offset;
			hud.MoveLower(0f - state.Lower);
			offset -= state.Offset;
			if (hud.HasPrevious)
			{
				hud.MoveRoot(0f - state.Offset);
			}
			List<IHudLine> list = Lines(hud);
			float num = LineHeight(hud.NameFontSize);
			float num2 = (float)list.Count * num;
			PlaceLines(hud, list, num);
			state.Lower = 0f - num2;
			state.Offset = ((offset < 0f) ? (0f - num2) : num2);
			state.LineHeight = num;
			hud.MoveLower(state.Lower);
			hud.Offset = offset + state.Offset;
			if (hud.HasPrevious)
			{
				hud.MoveRoot(state.Offset);
			}
			hud.Marker = ((list.Count == 0) ? null : ("MycoHudLines|" + Format(state.Lower) + "|" + Format(state.Offset) + "|" + Format(state.LineHeight)));
		}

		private static bool TryParse(string marker, out State state)
		{
			state = default(State);
			if (marker == null || !marker.StartsWith("MycoHudLines|", StringComparison.Ordinal))
			{
				return false;
			}
			string[] array = marker.Split('|');
			if (array.Length < 4)
			{
				return false;
			}
			state.Lower = Parse(array[1]);
			state.Offset = Parse(array[2]);
			state.LineHeight = Parse(array[3]);
			return true;
		}

		private static string Format(float v)
		{
			return v.ToString("R", CultureInfo.InvariantCulture);
		}

		private static float Parse(string s)
		{
			if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return 0f;
			}
			return result;
		}
	}
	public sealed class UnityTeammateHud : ITeammateHud
	{
		private sealed class Line : IHudLine
		{
			public readonly TextMeshProUGUI Text;

			public string Name
			{
				get
				{
					return ((Object)Text).name;
				}
				set
				{
					((Object)Text).name = value;
				}
			}

			public Line(TextMeshProUGUI text)
			{
				Text = text;
			}
		}

		private readonly TeammateHUD hud;

		private readonly TextMeshProUGUI name;

		public static bool Available => true;

		public float NameFontSize => ((TMP_Text)name).fontSize;

		public bool HasPrevious
		{
			get
			{
				if ((Object)(object)hud.Previous != (Object)null)
				{
					return ((Component)hud).transform is RectTransform;
				}
				return false;
			}
		}

		public float Offset
		{
			get
			{
				return hud.offset;
			}
			set
			{
				hud.offset = value;
			}
		}

		public string Marker
		{
			get
			{
				Transform val = FindMarker();
				if (!((Object)(object)val != (Object)null))
				{
					return null;
				}
				return ((Object)val).name;
			}
			set
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				Transform val = FindMarker();
				if (value == null)
				{
					if (!((Object)(object)val == (Object)null))
					{
						((Object)val).name = "MycoHudLines (removed)";
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
				}
				else if ((Object)(object)val == (Object)null)
				{
					GameObject val2 = new GameObject(value);
					val2.transform.SetParent(((Component)hud).transform, false);
					val2.SetActive(false);
				}
				else
				{
					((Object)val).name = value;
				}
			}
		}

		public IEnumerable<IHudLine> Siblings
		{
			get
			{
				Transform parent = ((TMP_Text)name).transform.parent;
				for (int i = 0; i < parent.childCount; i++)
				{
					TextMeshProUGUI component = ((Component)parent.GetChild(i)).GetComponent<TextMeshProUGUI>();
					if ((Object)(object)component != (Object)null && (Object)(object)component != (Object)(object)name)
					{
						yield return new Line(component);
					}
				}
			}
		}

		public static TextMeshProUGUI AddText(TeammateHUD hud, string id, int order)
		{
			UnityTeammateHud unityTeammateHud = For(hud);
			if (unityTeammateHud == null)
			{
				return null;
			}
			return ((Line)TeammateHudLines.Add(unityTeammateHud, id, order)).Text;
		}

		public static void Remove(TeammateHUD hud, string id)
		{
			UnityTeammateHud unityTeammateHud = For(hud);
			if (unityTeammateHud != null)
			{
				TeammateHudLines.Remove(unityTeammateHud, id);
			}
		}

		public static void Place(TeammateHUD hud)
		{
			UnityTeammateHud unityTeammateHud = For(hud);
			if (unityTeammateHud != null)
			{
				TeammateHudLines.Place(unityTeammateHud);
			}
		}

		private static UnityTeammateHud For(TeammateHUD hud)
		{
			if (!Available || (Object)(object)hud == (Object)null)
			{
				return null;
			}
			TextMeshProUGUI nameText = hud.nameText;
			if (!((Object)(object)nameText != (Object)null))
			{
				return null;
			}
			return new UnityTeammateHud(hud, nameText);
		}

		private UnityTeammateHud(TeammateHUD hud, TextMeshProUGUI name)
		{
			this.hud = hud;
			this.name = name;
		}

		private Transform FindMarker()
		{
			Transform transform = ((Component)hud).transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				if (((Object)child).name.StartsWith("MycoHudLines|", StringComparison.Ordinal))
				{
					return child;
				}
			}
			return null;
		}

		public IHudLine CreateLine(string lineName)
		{
			TextMeshProUGUI obj = Object.Instantiate<TextMeshProUGUI>(name, ((TMP_Text)name).transform.parent, false);
			((Object)obj).name = lineName;
			((TMP_Text)obj).text = "";
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).richText = false;
			((TMP_Text)obj).enableAutoSizing = false;
			((TMP_Text)obj).fontSize = ((TMP_Text)name).fontSize;
			((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)0;
			((TMP_Text)obj).rectTransform.SetSizeWithCurrentAnchors((Axis)0, 360f);
			return new Line(obj);
		}

		public void DestroyLine(IHudLine line)
		{
			TextMeshProUGUI text = ((Line)line).Text;
			((Component)text).gameObject.SetActive(false);
			Object.Destroy((Object)(object)((Component)text).gameObject);
		}

		public void MoveLower(float dy)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (dy == 0f)
			{
				return;
			}
			List<RectTransform> list = new List<RectTransform>();
			Graphic[] array = (Graphic[])(object)new Graphic[3]
			{
				(Graphic)hud.classText,
				(Graphic)hud.titleText,
				hud.loadingBarParent
			};
			foreach (Graphic val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					list.Add(val.rectTransform);
				}
			}
			foreach (RectTransform item in TeammateHudLines.TopLevel(list, ((TMP_Text)name).rectTransform, (RectTransform a, RectTransform b) => ((Transform)a).IsChildOf((Transform)(object)b)))
			{
				item.anchoredPosition += new Vector2(0f, dy);
			}
		}

		public void MoveRoot(float dy)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)hud).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (val != null)
			{
				val.anchoredPosition += new Vector2(0f, dy);
			}
		}

		public void PlaceLine(IHudLine line, float below)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)((Line)line).Text).rectTransform.anchoredPosition = ((TMP_Text)name).rectTransform.anchoredPosition + new Vector2(0f, 0f - below);
		}
	}
	public static class MacaronCore
	{
		public const string Guid = "doku_macaron.mycopunk.macaroncore";

		public const string Name = "Macaron Core";

		public const string Version = "1.1.0";
	}
	public static class ModsMenu
	{
		private abstract class Row
		{
			public GameObject Go;

			public ConfigEntryBase Entry;

			public string Owner;

			public TextMeshProUGUI Name;

			public HoverInfoText Hover;

			public abstract void Refresh();
		}

		private sealed class ToggleRow : Row
		{
			public RectTransform Knob;

			public Image Icon;

			public float Thickness;

			public override void Refresh()
			{
				ShowToggle(this, (bool)Entry.BoxedValue);
			}
		}

		private sealed class ColorRow : Row
		{
			public ScrollBar Bar;

			public Graphic Fill;

			public override void Refresh()
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				ShowColor(this, (Color)Entry.BoxedValue);
			}
		}

		[HarmonyPatch(typeof(PlayerOptions), "Awake")]
		private static class AwakePatch
		{
			[HarmonyPrefix]
			private static void Prefix(PlayerOptions __instance)
			{
				try
				{
					Build(__instance);
				}
				catch (Exception ex)
				{
					_log.LogWarning((object)("MODS tab could not be built: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(PlayerOptions), "OnOpen")]
		private static class OnOpenPatch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				OnOpened();
			}
		}

		[HarmonyPatch(typeof(TextBlocks), "Initialize")]
		private static class LanguagePatch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				RefreshLabels();
			}
		}

		private sealed class Item
		{
			public ConfigEntryBase Entry;

			public string Label;

			public string Owner;
		}

		private sealed class Group
		{
			public string Mod;

			public readonly List<Item> Items = new List<Item>();
		}

		private const string BuilderKey = "MycopunkShared.ModsMenu.v1.builder";

		private const string TabName = "Mods";

		private const float Step = 70f;

		private static ManualLogSource _log;

		private static readonly List<Row> Rows = new List<Row>();

		private static Transform _items;

		private static Transform _toggleTemplate;

		private static Transform _colorTemplate;

		private static string[] _groupNames = Array.Empty<string>();

		public static void Install(Harmony harmony, BaseUnityPlugin host)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Harmony val = null;
			try
			{
				AppDomain currentDomain = AppDomain.CurrentDomain;
				if (currentDomain.GetData("MycopunkShared.ModsMenu.v1.builder") == null)
				{
					_log = Logger.CreateLogSource("ModsMenu");
					val = new Harmony("MycopunkShared.ModsMenu");
					val.CreateClassProcessor(typeof(AwakePatch)).Patch();
					TryPatch(val, typeof(OnOpenPatch));
					TryPatch(val, typeof(LanguagePatch));
					currentDomain.SetData("MycopunkShared.ModsMenu.v1.builder", host.Info.Metadata.GUID);
				}
			}
			catch (Exception ex)
			{
				try
				{
					if (val != null)
					{
						val.UnpatchSelf();
					}
				}
				catch (Exception ex2)
				{
					(_log ?? (_log = Logger.CreateLogSource("ModsMenu"))).LogWarning((object)("MODS tab patch cleanup failed: " + ex2));
				}
				(_log ?? (_log = Logger.CreateLogSource("ModsMenu"))).LogWarning((object)("MODS tab disabled: " + ex));
			}
		}

		private static void TryPatch(Harmony harmony, Type patch)
		{
			try
			{
				harmony.CreateClassProcessor(patch).Patch();
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("MODS tab: " + patch.Name + " not applied: " + ex.Message));
			}
		}

		private static void OnOpened()
		{
			try
			{
				Refresh();
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("MODS tab refresh failed: " + ex.Message));
			}
		}

		public static void Refresh()
		{
			if ((Object)(object)_items == (Object)null || (Object)(object)_toggleTemplate == (Object)null)
			{
				return;
			}
			List<Group> list = CollectEntries();
			Item[] array = (from i in list.SelectMany((Group g) => g.Items)
				where i.Entry.SettingType == typeof(bool) || (Object)(object)_colorTemplate != (Object)null
				select i).ToArray();
			Row[] array2 = Rows.Where((Row r) => (Object)(object)r.Go != (Object)null && (Object)(object)r.Go.transform.parent == (Object)(object)_items).ToArray();
			bool flag = _groupNames.SequenceEqual(list.Select((Group g) => g.Mod)) && array2.Length == array.Length;
			int num = 0;
			while (flag && num < array2.Length)
			{
				flag = array2[num].Owner == array[num].Owner && array2[num].Entry.Definition.Equals(array[num].Entry.Definition) && array2[num].Entry.SettingType == array[num].Entry.SettingType;
				num++;
			}
			if (flag)
			{
				for (int num2 = 0; num2 < array2.Length; num2++)
				{
					array2[num2].Entry = array[num2].Entry;
					array2[num2].Refresh();
				}
			}
			else
			{
				Populate(_items, _toggleTemplate, _colorTemplate, list);
			}
			RefreshLabels();
		}

		private static bool Rebind(Row row)
		{
			if (!Chainloader.PluginInfos.TryGetValue(row.Owner, out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return false;
			}
			ConfigEntryBase value2 = ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)value.Instance.Config).FirstOrDefault((KeyValuePair<ConfigDefinition, ConfigEntryBase> p) => p.Key.Equals(row.Entry.Definition)).Value;
			if (value2 == null || value2.SettingType != row.Entry.SettingType)
			{
				return false;
			}
			row.Entry = value2;
			return true;
		}

		private static List<Group> CollectEntries()
		{
			List<Group> list = new List<Group>();
			foreach (PluginInfo item in Chainloader.PluginInfos.Values.OrderBy<PluginInfo, string>((PluginInfo i) => i.Metadata.Name, StringComparer.OrdinalIgnoreCase))
			{
				ConfigFile val;
				try
				{
					val = (((Object)(object)item.Instance != (Object)null) ? item.Instance.Config : null);
				}
				catch
				{
					continue;
				}
				if (val == null)
				{
					continue;
				}
				string mod = (item.Metadata.Name.StartsWith("Mycopunk ", StringComparison.Ordinal) ? item.Metadata.Name.Substring(9) : item.Metadata.Name);
				Group obj2 = new Group
				{
					Mod = mod
				};
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item2 in val)
				{
					ConfigEntryBase value = item2.Value;
					if (!(value.SettingType != typeof(bool)) || !(value.SettingType != typeof(Color)))
					{
						ConfigDescription description = value.Description;
						string text = ModsMenuTag.Find((description != null) ? description.Tags : null);
						if (text != null)
						{
							obj2.Items.Add(new Item
							{
								Entry = value,
								Label = ((text.Length > 0) ? text : item2.Key.Key),
								Owner = item.Metadata.GUID
							});
						}
					}
				}
				if (obj2.Items.Count > 0)
				{
					list.Add(obj2);
				}
			}
			return list;
		}

		private static void Build(PlayerOptions po)
		{
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Expected O, but got Unknown
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Expected O, but got Unknown
			RectTransform[] sections = po.sections;
			DefaultButton[] sectionButtons = po.sectionButtons;
			if (sections == null || sectionButtons == null)
			{
				_log.LogWarning((object)"PlayerOptions.sections / sectionButtons not found; no MODS tab.");
			}
			else
			{
				if (sections.Any((RectTransform s) => (Object)(object)s != (Object)null && ((Object)s).name == "Mods"))
				{
					return;
				}
				List<Group> list = CollectEntries();
				if (list.Count == 0)
				{
					_log.LogInfo((object)"No config entries are marked for the MODS tab.");
					return;
				}
				List<DefaultButton> list2 = sectionButtons.ToList();
				DefaultButton val = ((IEnumerable<DefaultButton>)list2).FirstOrDefault((Func<DefaultButton, bool>)((DefaultButton b) => (Object)(object)b != (Object)null && ((Object)b).name == "Graphics"));
				RectTransform val2 = ((IEnumerable<RectTransform>)sections).FirstOrDefault((Func<RectTransform, bool>)((RectTransform s) => (Object)(object)s != (Object)null && ((Object)s).name == "Debug"));
				RectTransform val3 = ((IEnumerable<RectTransform>)sections).FirstOrDefault((Func<RectTransform, bool>)((RectTransform s) => (Object)(object)s != (Object)null && ((Object)s).name == "Gameplay"));
				Transform val4 = (((Object)(object)val3 != (Object)null) ? ((Transform)val3).Find("Items/HideHUD") : null);
				Transform val5 = (((Object)(object)val3 != (Object)null) ? ((Transform)val3).Find("Items/UIColor") : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val4 == (Object)null)
				{
					_log.LogWarning((object)"MODS tab: Graphics button, Debug section or Gameplay/Items/HideHUD not found; no MODS tab.");
					return;
				}
				if ((Object)(object)val5 == (Object)null)
				{
					_log.LogWarning((object)"MODS tab: Gameplay/Items/UIColor not found; colour entries are left out.");
				}
				int index = sections.Length;
				RectTransform val6 = (RectTransform)((Component)val).transform;
				GameObject val7 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Transform)val6).parent, false);
				((Object)val7).name = "Mods";
				RectTransform val8 = (RectTransform)val7.transform;
				val8.anchoredPosition = val6.anchoredPosition + new Vector2(0f, -70f);
				foreach (DefaultButton item in list2)
				{
					if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)val)
					{
						Transform transform = ((Component)item).transform;
						RectTransform val9 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
						if (val9 != null && val9.anchoredPosition.y <= val8.anchoredPosition.y + 0.5f)
						{
							val9.anchoredPosition += new Vector2(0f, -70f);
						}
					}
				}
				SetTextBlock[] componentsInChildren = val7.GetComponentsInChildren<SetTextBlock>(true);
				foreach (SetTextBlock val10 in componentsInChildren)
				{
					if ((Object)(object)val10 != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)val10);
					}
				}
				TextMeshProUGUI componentInChildren = val7.GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = "MODS";
				}
				DefaultButton val11 = (DefaultButton)val7.GetComponent(((object)val).GetType());
				ReplaceEvent((Button)(object)val11, delegate
				{
					po.SetSection(index);
				});
				GameObject val12 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Transform)val2).parent, false);
				((Object)val12).name = "Mods";
				val12.SetActive(false);
				Transform val13 = val12.transform.Find("Items");
				if ((Object)(object)val13 == (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val12);
					Object.DestroyImmediate((Object)(object)val7);
					_log.LogWarning((object)"Debug/Items not found; no MODS tab.");
					return;
				}
				for (int num2 = val13.childCount - 1; num2 >= 0; num2--)
				{
					Object.DestroyImmediate((Object)(object)((Component)val13.GetChild(num2)).gameObject);
				}
				int num3 = Populate(val13, val4, val5, list);
				po.sections = sections.Concat((IEnumerable<RectTransform>)(object)new RectTransform[1] { (RectTransform)val12.transform }).ToArray();
				po.sectionButtons = sectionButtons.Concat((IEnumerable<DefaultButton>)(object)new DefaultButton[1] { val11 }).ToArray();
				_items = val13;
				_toggleTemplate = val4;
				_colorTemplate = val5;
				_log.LogInfo((object)("MODS tab added with " + num3 + " entries in " + list.Count + " groups."));
			}
		}

		private static int Populate(Transform items, Transform toggleTemplate, Transform colorTemplate, List<Group> groups)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			GameObject val = new GameObject("ModsMenu holder");
			val.SetActive(false);
			List<Row> list = new List<Row>();
			try
			{
				foreach (Group group in groups)
				{
					MakeHeading(((Component)toggleTemplate).gameObject, val.transform, group.Mod);
					foreach (Item item in group.Items)
					{
						Row row = ((item.Entry.SettingType == typeof(bool)) ? ((Row)MakeToggleRow(((Component)toggleTemplate).gameObject, val.transform, item)) : ((Row)(((Object)(object)colorTemplate != (Object)null) ? MakeColorRow(((Component)colorTemplate).gameObject, val.transform, item) : null)));
						if (row != null)
						{
							list.Add(row);
							row.Refresh();
						}
					}
				}
				for (int num = items.childCount - 1; num >= 0; num--)
				{
					GameObject gameObject = ((Component)items.GetChild(num)).gameObject;
					gameObject.SetActive(false);
					Object.Destroy((Object)(object)gameObject);
				}
				Rows.RemoveAll((Row r) => (Object)(object)r.Go == (Object)null || (Object)(object)r.Go.transform.parent == (Object)(object)items);
				while (val.transform.childCount > 0)
				{
					val.transform.GetChild(0).SetParent(items, false);
				}
				Rows.AddRange(list);
				_groupNames = groups.Select((Group g) => g.Mod).ToArray();
				return list.Count;
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}

		private static GameObject MakeHeading(GameObject template, Transform holder, string mod)
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(template, holder, false);
			((Object)val).name = "Mod heading " + mod;
			Transform val2 = val.transform.Find("Name");
			TextMeshProUGUI val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)val3 == (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
			for (int num = val.transform.childCount - 1; num >= 0; num--)
			{
				if ((Object)(object)val.transform.GetChild(num) != (Object)(object)val2)
				{
					Object.DestroyImmediate((Object)(object)((Component)val.transform.GetChild(num)).gameObject);
				}
			}
			foreach (Component item in (from c in val.GetComponents<Component>()
				where c is MonoBehaviour && !(c is Graphic) && !(c is LayoutElement)
				select c).ToList())
			{
				Object.DestroyImmediate((Object)(object)item);
			}
			foreach (Graphic item2 in val.GetComponents<Graphic>().ToList())
			{
				Object.DestroyImmediate((Object)(object)item2);
			}
			CanvasRenderer component = val.GetComponent<CanvasRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			((TMP_Text)val3).text = mod.ToUpperInvariant();
			((TMP_Text)val3).fontStyle = (FontStyles)(((TMP_Text)val3).fontStyle | 1);
			((TMP_Text)val3).fontSize = ((TMP_Text)val3).fontSize * 1.15f;
			LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			RectTransform val4 = (RectTransform)val.transform;
			float minHeight = (obj.preferredHeight = val4.sizeDelta.y + 20f);
			obj.minHeight = minHeight;
			return val;
		}

		private static ToggleRow MakeToggleRow(GameObject template, Transform holder, Item item)
		{
			GameObject val = Object.Instantiate<GameObject>(template, holder, false);
			((Object)val).name = "Mod " + item.Label;
			ToggleOption[] components = val.GetComponents<ToggleOption>();
			foreach (ToggleOption val2 in components)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			Button component = val.GetComponent<Button>();
			Transform obj = val.transform.Find("Name");
			TextMeshProUGUI val3 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			ColorButton val4 = (ColorButton)(object)((component is ColorButton) ? component : null);
			Graphic val5 = (Graphic)((val4 != null) ? ((object)val4.mainGraphic) : ((object)(((Object)(object)component != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null)));
			Transform obj2 = val.transform.Find("Button/Icon");
			Image val6 = ((obj2 != null) ? ((Component)obj2).GetComponent<Image>() : null);
			if ((Object)(object)component == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null)
			{
				_log.LogWarning((object)("MODS tab: the toggle row layout is not as expected; skipping " + item.Label));
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
			OutlineGraphic val7 = default(OutlineGraphic);
			float thickness = (val.TryGetComponent<OutlineGraphic>(ref val7) ? val7.thickness : 1.5f);
			ToggleRow row = new ToggleRow
			{
				Go = val,
				Entry = item.Entry,
				Owner = item.Owner,
				Knob = val5.rectTransform,
				Icon = val6,
				Thickness = thickness,
				Name = val3
			};
			AddLabel(row);
			ReplaceEvent(component, delegate
			{
				try
				{
					if (Rebind(row))
					{
						bool flag = !(bool)row.Entry.BoxedValue;
						row.Entry.BoxedValue = flag;
						ShowToggle(row, flag);
					}
				}
				catch (Exception ex)
				{
					_log.LogWarning((object)("MODS tab: could not change " + item.Label + ": " + ex.Message));
				}
			});
			return row;
		}

		private static ColorRow MakeColorRow(GameObject template, Transform holder, Item item)
		{
			GameObject val = Object.Instantiate<GameObject>(template, holder, false);
			((Object)val).name = "Mod " + item.Label;
			ColorOption[] components = val.GetComponents<ColorOption>();
			foreach (ColorOption val2 in components)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			Transform obj = val.transform.Find("Name");
			TextMeshProUGUI val3 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			ScrollBar componentInChildren = val.GetComponentInChildren<ScrollBar>(true);
			object obj2;
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				obj2 = null;
			}
			else
			{
				Transform obj3 = ((Component)componentInChildren).transform.Find("F");
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<Graphic>() : null);
			}
			Graphic val4 = (Graphic)obj2;
			UnityEvent<Vector2> val5 = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.OnDrag : null);
			if ((Object)(object)val3 == (Object)null || (Object)(object)componentInChildren == (Object)null || (Object)(object)val4 == (Object)null || val5 == null)
			{
				_log.LogWarning((object)("MODS tab: the colour row layout is not as expected; skipping " + item.Label));
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
			CharacterGraphic[] components2 = ((Component)val4).GetComponents<CharacterGraphic>();
			foreach (CharacterGraphic val6 in components2)
			{
				if ((Object)(object)val6 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val6);
				}
			}
			for (int j = 0; j < ((UnityEventBase)val5).GetPersistentEventCount(); j++)
			{
				((UnityEventBase)val5).SetPersistentListenerState(j, (UnityEventCallState)0);
			}
			ColorRow row = new ColorRow
			{
				Go = val,
				Entry = item.Entry,
				Owner = item.Owner,
				Bar = componentInChildren,
				Fill = val4,
				Name = val3
			};
			AddLabel(row);
			val5.AddListener((UnityAction<Vector2>)delegate(Vector2 v)
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (Rebind(row))
					{
						Color val7 = (Color)row.Entry.BoxedValue;
						Color val8 = Color.HSVToRGB(Mathf.Clamp01(v.x), Mathf.Clamp01(v.y), 1f);
						val8.a = val7.a;
						row.Entry.BoxedValue = val8;
						row.Fill.color = new Color(val8.r, val8.g, val8.b, 1f);
					}
				}
				catch (Exception ex)
				{
					_log.LogWarning((object)("MODS tab: could not change " + item.Label + ": " + ex.Message));
				}
			});
			return row;
		}

		private static void RefreshLabels()
		{
			foreach (Row row in Rows)
			{
				if ((Object)(object)row.Go != (Object)null)
				{
					SetLabel(row);
				}
			}
		}

		private static void AddLabel(Row row)
		{
			ConfigDescription description = row.Entry.Description;
			if (!string.IsNullOrEmpty((description != null) ? description.Description : null))
			{
				row.Hover = row.Go.AddComponent<HoverInfoText>();
			}
			SetLabel(row);
		}

		private static void SetLabel(Row row)
		{
			string language = ModsMenuTag.Language(TextBlocks.LanguageIndex);
			ConfigDescription description = row.Entry.Description;
			string text = ModsMenuTag.Find((description != null) ? description.Tags : null, language);
			((TMP_Text)row.Name).text = (string.IsNullOrEmpty(text) ? row.Entry.Definition.Key : text);
			if ((Object)(object)row.Hover != (Object)null)
			{
				row.Hover.text = ModsMenuTag.Description(row.Entry.Description.Tags, language, row.Entry.Description.Description);
			}
		}

		private static void ShowToggle(ToggleRow row, bool on)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)row.Knob).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!((Object)(object)val == (Object)null))
			{
				Rect rect = val.rect;
				float num = ((Rect)(ref rect)).width * 0.5f;
				rect = row.Knob.rect;
				float num2 = num - ((Rect)(ref rect)).width * 0.5f - row.Thickness;
				row.Knob.anchoredPosition = new Vector2(on ? num2 : (0f - num2), row.Knob.anchoredPosition.y);
				Global instance = Global.Instance;
				Sprite val2 = ((!((Object)(object)instance != (Object)null)) ? null : (on ? instance.CheckmarkIcon : instance.CrossIcon));
				if ((Object)(object)val2 != (Object)null)
				{
					row.Icon.sprite = val2;
				}
			}
		}

		private static void ShowColor(ColorRow row, Color color)
		{
			//IL_0000: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(color, ref num, ref num2, ref num3);
			row.Bar.SetScrollNoInvoke(new Vector2(num, num2));
			row.Fill.color = new Color(color.r, color.g, color.b, 1f);
		}

		private static void ReplaceEvent(Button target, Action action)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			UnityEvent val = new UnityEvent();
			val.AddListener(new UnityAction(action.Invoke));
			target.OnClickUp = val;
		}
	}
	public static class ModChannels
	{
		public const string DpsStatsKey = "MycopunkShared.DpsChecker.Stats.v1";

		public static void Publish(string key, object value)
		{
			try
			{
				AppDomain.CurrentDomain.SetData(key, value);
			}
			catch
			{
			}
		}

		public static T Get<T>(string key) where T : class
		{
			try
			{
				return AppDomain.CurrentDomain.GetData(key) as T;
			}
			catch
			{
				return null;
			}
		}

		public static string FormatDps(float max, int kills, bool estimated)
		{
			return max.ToString("R", CultureInfo.InvariantCulture) + "\t" + kills.ToString(CultureInfo.InvariantCulture) + "\t" + (estimated ? "1" : "0");
		}

		public static bool TryParseDps(string text, out float max, out int kills, out bool estimated)
		{
			max = 0f;
			kills = 0;
			estimated = false;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] array = text.Split('\t');
			if (array.Length < 3)
			{
				return false;
			}
			estimated = array[2] == "1";
			if (float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out max))
			{
				return int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out kills);
			}
			return false;
		}
	}
	public static class ModSetup
	{
		public static void Try(ManualLogSource log, string what, Action action)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				log.LogError((object)("Could not set up " + what + "; it is off: " + ex));
			}
		}

		public static void PatchTogether(Harmony harmony, params Type[] patches)
		{
			HashSet<Type> hashSet = new HashSet<Type>();
			try
			{
				foreach (Type type in patches)
				{
					hashSet.Add(type);
					harmony.CreateClassProcessor(type).Patch();
				}
			}
			catch (Exception ex)
			{
				List<Exception> list = new List<Exception>();
				foreach (MethodBase item2 in harmony.GetPatchedMethods().ToList())
				{
					Patches patchInfo = Harmony.GetPatchInfo(item2);
					if (patchInfo == null)
					{
						continue;
					}
					foreach (Patch item3 in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers))
					{
						if (!(item3.owner != harmony.Id) && hashSet.Contains(item3.PatchMethod.DeclaringType))
						{
							try
							{
								harmony.Unpatch(item2, item3.PatchMethod);
							}
							catch (Exception item)
							{
								list.Add(item);
							}
						}
					}
				}
				if (list.Count > 0)
				{
					throw new AggregateException("Patching failed, and taking back the applied patches failed too.", new Exception[1] { ex }.Concat(list));
				}
				throw;
			}
		}
	}
	public static class ModsMenuTag
	{
		public const string Tag = "MycopunkShared.ModsMenu";

		public static object[] Label(string key, IDictionary<string, Dictionary<string, string>> names, IDictionary<string, Dictionary<string, string>> descriptions = null)
		{
			if (names == null || !names.TryGetValue("en", out var value) || !value.TryGetValue(key, out var value2))
			{
				throw new ArgumentException("Missing English MODS menu text: " + key);
			}
			List<object> list = new List<object>
			{
				"MycopunkShared.ModsMenu",
				"MycopunkShared.ModsMenu:" + value2
			};
			foreach (KeyValuePair<string, Dictionary<string, string>> name in names)
			{
				if (name.Key != "en" && name.Value.TryGetValue(key, out var value3) && !string.IsNullOrEmpty(value3))
				{
					list.Add("MycopunkShared.ModsMenu." + name.Key + ":" + value3);
				}
			}
			if (descriptions != null)
			{
				foreach (KeyValuePair<string, Dictionary<string, string>> description in descriptions)
				{
					if (description.Value.TryGetValue(key, out var value4) && !string.IsNullOrEmpty(value4))
					{
						list.Add("MycopunkShared.ModsMenu.description." + description.Key + ":" + value4);
					}
				}
			}
			return list.ToArray();
		}

		public static string Language(int gameLanguageIndex)
		{
			if (gameLanguageIndex != 8)
			{
				return "en";
			}
			return "ja";
		}

		public static string Description(object[] tags, string language, string fallback)
		{
			string text = "MycopunkShared.ModsMenu.description." + language + ":";
			if (tags != null)
			{
				for (int i = 0; i < tags.Length; i++)
				{
					if (tags[i] is string text2 && text2.StartsWith(text, StringComparison.Ordinal) && text2.Length > text.Length)
					{
						return text2.Substring(text.Length);
					}
				}
			}
			return fallback;
		}

		public static string Find(object[] tags, string language = "en")
		{
			if (tags == null)
			{
				return null;
			}
			string text = null;
			string text2 = null;
			bool flag = false;
			for (int i = 0; i < tags.Length; i++)
			{
				if (tags[i] is string text3)
				{
					if (text3 == "MycopunkShared.ModsMenu")
					{
						flag = true;
					}
					else if (text3.StartsWith("MycopunkShared.ModsMenu:", StringComparison.Ordinal))
					{
						flag = true;
						text = text3.Substring("MycopunkShared.ModsMenu".Length + 1);
					}
					else if (text3.StartsWith("MycopunkShared.ModsMenu." + language + ":", StringComparison.Ordinal))
					{
						text2 = text3.Substring("MycopunkShared.ModsMenu".Length + language.Length + 2);
					}
				}
			}
			if (!flag)
			{
				return null;
			}
			string text4;
			if (string.IsNullOrEmpty(text2))
			{
				text4 = text;
				if (text4 == null)
				{
					return "";
				}
			}
			else
			{
				text4 = text2;
			}
			return text4;
		}
	}
	public sealed class SessionLogFile : IDisposable
	{
		private sealed class Listener : ILogListener, IDisposable
		{
			private readonly ManualLogSource _source;

			private readonly StreamWriter _writer;

			public Listener(ManualLogSource source, string path)
			{
				_source = source;
				_writer = new StreamWriter(new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				_writer.NewLine = "\n";
				_writer.AutoFlush = true;
			}

			public void LogEvent(object sender, LogEventArgs e)
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				if ((object)e.Source != _source)
				{
					return;
				}
				try
				{
					_writer.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " [" + ((object)e.Level/*cast due to .constrained prefix*/).ToString() + "] " + e.Data);
				}
				catch
				{
				}
			}

			public void Dispose()
			{
				try
				{
					_writer.Dispose();
				}
				catch
				{
				}
			}
		}

		private Listener _listener;

		public string FilePath { get; }

		private SessionLogFile(Listener listener, string path)
		{
			_listener = listener;
			FilePath = path;
		}

		public static string LogDirectory(string folder)
		{
			string text = Path.Combine(Paths.BepInExRootPath, folder, "logs");
			Directory.CreateDirectory(text);
			return text;
		}

		public static SessionLogFile Open(ManualLogSource log, string folder, string prefix)
		{
			try
			{
				string path = Path.Combine(LogDirectory(folder), prefix + "-" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".log");
				Listener listener = new Listener(log, path);
				Logger.Listeners.Add((ILogListener)(object)listener);
				return new SessionLogFile(listener, path);
			}
			catch (Exception ex)
			{
				log.LogWarning((object)("Session log file disabled: " + ex.Message));
				return null;
			}
		}

		public void Dispose()
		{
			if (_listener != null)
			{
				Logger.Listeners.Remove((ILogListener)(object)_listener);
				_listener.Dispose();
				_listener = null;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}