Decompiled source of TellMeCosmetics v1.0.3

TellMeCosmetics.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
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.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using HarmonyLib;
using Il2Cpp;
using Il2CppBehaviorDesigner.Runtime;
using Il2CppCharacterCustomization;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRandomGeneration;
using Il2CppRandomGeneration.Contracts;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppTMPro;
using Il2CppValkoGames.Labyrinthine.Cases;
using Il2CppValkoGames.Labyrinthine.Cases.Objectives;
using Il2CppValkoGames.Labyrinthine.Data;
using Il2CppValkoGames.Labyrinthine.Misc.TimeInfo;
using Il2CppValkoGames.Labyrinthine.Monsters;
using Il2CppValkoGames.Labyrinthine.UI.Customization;
using MelonLoader;
using MelonLoader.InternalUtils;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using TellMeCosmetics;
using TellMeCosmetics.Config;
using TellMeCosmetics.Predict;
using TellMeCosmetics.UI;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: VerifyLoaderVersion(0, 6, 6, true)]
[assembly: MelonInfo(typeof(CustomizationPickupFinderMod), "Tell Me Cosmetics", "1.0.3", "1.0.3", null)]
[assembly: MelonGame("Valko Game Studios", "Labyrinthine")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TellMeCosmetics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+9e8edc3c424b4033936387a188e00bef360dd774")]
[assembly: AssemblyProduct("Tell Me Cosmetics")]
[assembly: AssemblyTitle("TellMeCosmetics")]
[assembly: AssemblyVersion("1.0.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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;
		}
	}
}
internal static class ModInfo
{
	public const string Name = "Tell Me Cosmetics";

	public const string Version = "1.0.3";

	public const string Author = "LimitBRK";
}
namespace TellMeCosmetics
{
	[HarmonyPatch(typeof(CustomizationPickup), "Start")]
	internal class Customization_SpawnItemListener
	{
		private static void Postfix(CustomizationPickup __instance)
		{
			CustomizationPickupFinderMod.Instance?.Show(__instance);
		}
	}
	[HarmonyPatch(typeof(CustomizationPickup), "Pickup")]
	internal class Customization_PickUpListener
	{
		private static void Postfix(CustomizationPickup __instance)
		{
			CustomizationPickupFinderMod.Instance?.Pickup(__instance.ItemID);
		}
	}
	[HarmonyPatch(typeof(RndCustomizationItemsManager), "SpawnCustomizationItems")]
	internal class Customization_RndSpawnListener
	{
		private static void Prefix(RndCustomizationItemsManager __instance)
		{
			CustomizationPickupFinderMod.Instance?.CapturePool(__instance);
		}
	}
	[HarmonyPatch(typeof(ContractUI), "UpdateUI")]
	internal class Contract_UpdateUIListener
	{
		private static void Postfix(ContractUI __instance)
		{
			CustomizationPickupFinderMod.Instance?.ShowPrediction(__instance);
		}
	}
	[HarmonyPatch(typeof(CustomizationSave), "Load")]
	internal class Customization_SaveLoadListener
	{
		private static void Postfix(CustomizationSave __result)
		{
			CustomizationPickupFinderMod.Instance?.UpdateSave(__result);
		}
	}
	public class CustomizationPickupFinderMod : MelonMod
	{
		private CustomizationSave SaveInstance;

		private ItemsCollectionSO itemsCollection;

		private ItemAlertUI alertui;

		private CustomizationUISlot menuSlot;

		private GameplayConfig config;

		private Queue<CustomizationPickup> pendingItems = new Queue<CustomizationPickup>();

		private bool isProcessingItems;

		private readonly HashSet<IntPtr> waiting = new HashSet<IntPtr>();

		internal static CustomizationPickupFinderMod Instance { get; private set; }

		public override void OnInitializeMelon()
		{
			config = ConfigManager.Instance;
			Instance = this;
			((MelonBase)this).LoggerInstance.Msg("TellMeCosmetics Mod Loaded!!!");
			ScenePreload.Start(config.DebugMazeTests.Value);
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			((MelonBase)this).LoggerInstance.Msg($"SCENE {buildIndex}/{sceneName} Loaded!");
			MelonCoroutines.Start(InitItemsCollectionSO());
			if (buildIndex >= 3 && sceneName == "LoadingScreen")
			{
				MelonCoroutines.Start(ClearAlertUIAfterDelay());
			}
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			((MelonBase)this).LoggerInstance.Msg($"SCENE {buildIndex}/{sceneName} Initialized!");
			if (buildIndex == 1 && config.DebugMazeTests.Value)
			{
				GameRandomTest.Run();
			}
			if (buildIndex >= 1 && sceneName == "MainMenu" && (alertui == null || alertui.IsDestroy()))
			{
				MelonCoroutines.Start(InitUI());
			}
		}

		private IEnumerator InitItemsCollectionSO()
		{
			if ((Object)(object)itemsCollection != (Object)null)
			{
				yield break;
			}
			for (int attempts = 0; attempts < 3; attempts++)
			{
				ItemsCollectionSO[] array = Il2CppArrayBase<ItemsCollectionSO>.op_Implicit(Resources.FindObjectsOfTypeAll<ItemsCollectionSO>());
				if (array.Length != 0)
				{
					itemsCollection = array[0];
					((MelonBase)this).LoggerInstance.Msg("Init itemsCollectionSO Class");
					yield break;
				}
				yield return (object)new WaitForSeconds(0.1f);
			}
			((MelonBase)this).LoggerInstance.Warning("Failed to initialize ItemsCollectionSO after 3 attempts");
		}

		private IEnumerator InitUI()
		{
			yield return (object)new WaitForSeconds(0.2f);
			for (int attempts = 0; attempts < 3; attempts++)
			{
				if (TryInitializeUI())
				{
					((MelonBase)this).LoggerInstance.Msg("UI initialized successfully.");
					yield break;
				}
				yield return (object)new WaitForSeconds(0.1f);
				((MelonBase)this).LoggerInstance.Warning($"UI initialization attempt {attempts + 1}/3 failed, retrying...");
			}
			((MelonBase)this).LoggerInstance.Error("Failed to initialize UI after 3 attempts");
		}

		private bool TryInitializeUI()
		{
			try
			{
				GameObject val = GameObject.Find("Global/Global Canvas/Player_UI/Tab Menu");
				if ((Object)(object)val == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("UI Tab Menu not found!");
					return false;
				}
				RectTransform component = val.GetComponent<RectTransform>();
				if ((Object)(object)component == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("UI RectTransform missing!");
					return false;
				}
				itemsCollection = ((IEnumerable<ItemsCollectionSO>)Resources.FindObjectsOfTypeAll<ItemsCollectionSO>()).FirstOrDefault();
				if ((Object)(object)itemsCollection == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("ItemsCollectionSO not found!");
					return false;
				}
				((MelonBase)this).LoggerInstance.Msg("Initializing UI components...");
				alertui = new ItemAlertUI(component, itemsCollection);
				return true;
			}
			catch (Exception value)
			{
				((MelonBase)this).LoggerInstance.Error($"[InitUI] Exception: {value}");
				return false;
			}
		}

		private IEnumerator ClearAlertUIAfterDelay()
		{
			yield return (object)new WaitForEndOfFrame();
			alertui?.Clear();
			((MelonBase)this).LoggerInstance.Msg("UI Cleared");
		}

		internal void Show(CustomizationPickup item)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Component)item).gameObject.transform.localPosition == Vector3.zero))
			{
				pendingItems.Enqueue(item);
				if (!isProcessingItems)
				{
					MelonCoroutines.Start(ProcessPendingItems());
				}
			}
		}

		private IEnumerator ProcessPendingItems()
		{
			isProcessingItems = true;
			while (pendingItems.Count > 0)
			{
				CustomizationPickup val = pendingItems.Dequeue();
				if (!(((Component)val).gameObject.transform.localPosition == Vector3.zero))
				{
					((MelonBase)this).LoggerInstance.Msg($"\ud83d\udce6Spawned Cosmetic ItemID {val.ItemID} {((Object)val).name}!");
					if (!config.RevealAll.Value && SaveInstance != null)
					{
						alertui?.Show(val, SaveInstance.IsItemUnlocked(val.ItemID));
					}
					else
					{
						alertui?.Show(val);
					}
					yield return (object)new WaitForSeconds(0.05f);
				}
			}
			isProcessingItems = false;
		}

		internal void Pickup(ushort itemID)
		{
			alertui?.Pickup(itemID);
		}

		internal void CapturePool(RndCustomizationItemsManager mgr)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected I4, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected I4, but got Unknown
			GameValues instance = GameValues.instance;
			Contract val = ((instance != null) ? instance.RandomMazeContract : null);
			ContractPredictor.Pool pool = ((val == null) ? null : ContractPredictor.Capture(mgr, (int)val.MazeType));
			if (pool != null && config.DebugMazeTests.Value)
			{
				ScenePreload.Check((int)val.MazeType, null, pool);
			}
			MazeGenerator instance2 = MazeGenerator.instance;
			if (val != null && !((Object)(object)instance2 == (Object)null) && config.DebugMazeTests.Value)
			{
				(int seed, int second, bool simulated) tuple = ContractPredictor.MazeSeeds(val);
				int item = tuple.seed;
				int item2 = tuple.second;
				bool item3 = tuple.simulated;
				bool flag = item == instance2.seed && item2 == instance2.secondSeed;
				((MelonBase)this).LoggerInstance.Msg($"\ud83d\udd2eLobby prediction for this contract: {ContractPredictor.Predict(val, out var _, out var _)?.ToString() ?? "none"} | \ud83c\udfafPipeline {((!item3) ? "NOT SIMULATED" : (flag ? "MATCH" : "MISMATCH"))} predicted {item}/{item2} actual {instance2.seed}/{instance2.secondSeed} (contract {val.Seed}/{val.SecondSeed})");
			}
		}

		private IEnumerator ShowWhenReady(ContractUI ui)
		{
			IntPtr ptr = ((Il2CppObjectBase)ui).Pointer;
			try
			{
				while (true)
				{
					yield return null;
					if (!((Object)(object)ui == (Object)null) && ui.Contract != null)
					{
						ContractPredictor.Predict(ui.Contract, wait: false, out var _, out var _, out var pending);
						if (!pending)
						{
							break;
						}
						ContractItemUI.Spin(ui);
						continue;
					}
					yield break;
				}
			}
			finally
			{
				waiting.Remove(ptr);
			}
			ShowPrediction(ui);
		}

		internal void ShowPrediction(ContractUI ui)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Invalid comparison between Unknown and I4
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			Contract contract = ui.Contract;
			if (contract == null || (Object)(object)ui.infoText == (Object)null)
			{
				return;
			}
			ContractItemUI.View view = new ContractItemUI.View();
			bool simulated = false;
			float chance;
			bool pending;
			int? num = ContractPredictor.Predict(contract, wait: false, out chance, out simulated, out pending);
			if (pending)
			{
				view.Loading = true;
				ContractItemUI.Show(ui, view);
				if (waiting.Add(((Il2CppObjectBase)ui).Pointer))
				{
					MelonCoroutines.Start(ShowWhenReady(ui));
				}
				return;
			}
			if (!simulated)
			{
				if ((int)contract.ContractType != 0)
				{
					view.AltIcon = "?";
				}
			}
			else if (num.HasValue)
			{
				int valueOrDefault = num.GetValueOrDefault();
				CustomizationItem val = (((Object)(object)itemsCollection != (Object)null && valueOrDefault < ((Il2CppArrayBase<CustomizationItem>)(object)itemsCollection.collection).Length) ? ((Il2CppArrayBase<CustomizationItem>)(object)itemsCollection.collection)[valueOrDefault] : null);
				bool flag = SaveInstance != null && !SaveInstance.IsItemUnlocked((ushort)valueOrDefault);
				bool flag2 = flag && !config.RevealAll.Value;
				bool flag3 = val != null && (int)val.BodyPart == 100;
				view.Icon = (flag3 ? null : ((val != null) ? val.Icon : null));
				view.AltIcon = (flag3 ? "♫" : "?");
				view.Silhouette = flag2;
				view.New = flag;
				if ((Object)(object)menuSlot == (Object)null)
				{
					menuSlot = ((IEnumerable<CustomizationUISlot>)Resources.FindObjectsOfTypeAll<CustomizationUISlot>()).FirstOrDefault();
				}
				CustomizationUISlot val2 = menuSlot;
				int num2 = ((val == null || flag2) ? (-1) : ((int)val.ItemRarity));
				if ((Object)(object)val2 != (Object)null && num2 >= 0 && num2 < ((Il2CppArrayBase<Color>)(object)val2.backgroundColors).Length && num2 < ((Il2CppArrayBase<Sprite>)(object)val2.backgroundSprites).Length)
				{
					object obj = ((Il2CppArrayBase<Sprite>)(object)val2.backgroundSprites)[num2];
					if (obj == null)
					{
						Image itemBackgroundImage = val2.itemBackgroundImage;
						obj = ((itemBackgroundImage != null) ? itemBackgroundImage.sprite : null);
					}
					view.Frame = (Sprite)obj;
					view.FrameColor = ((Il2CppArrayBase<Color>)(object)val2.backgroundColors)[num2];
				}
			}
			ContractItemUI.Show(ui, view);
		}

		internal void UpdateSave(CustomizationSave save)
		{
			if (save != null)
			{
				SaveInstance = save;
			}
		}
	}
}
namespace TellMeCosmetics.UI
{
	public static class ContractItemUI
	{
		public sealed class View
		{
			public Sprite Icon;

			public Sprite Frame;

			public Color FrameColor = Color.white;

			public string AltIcon;

			public bool Silhouette;

			public bool New;

			public bool Loading;
		}

		private const string Name = "TMC Contract Cosmetic";

		private const float Width = 100f;

		private const float IconHeight = 100f;

		private const float LabelHeight = 14f;

		private const float Border = 6f;

		private static readonly Vector2 BadgePos = new Vector2(26f, 50f);

		private static readonly Vector2 BadgeSize = new Vector2(56f, 24f);

		private const string NoteName = "TMC Note";

		private static Transform note;

		private const string LoadingName = "Circle Dash 2 64px - Stroke 10px";

		private static Sprite loadingSprite;

		private static bool loadingTried;

		private const float PaperW = 112f;

		private const float PaperH = 126f;

		private const int PxPerUnit = 2;

		private static Material silhouette;

		private static Texture2D paperTexture;

		public static void Show(ContractUI ui, View view)
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = ((Component)ui).transform.Find("TMC Contract Cosmetic");
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null) ?? Create(ui);
			GameObject gameObject = ((Component)val.transform.Find("Spinner")).gameObject;
			bool flag = view.Loading && (Object)(object)LoadingSprite() != (Object)null;
			if (view.Loading && !flag)
			{
				view.AltIcon = "…";
			}
			gameObject.SetActive(flag);
			bool flag2 = flag || (Object)(object)view.Icon != (Object)null || !string.IsNullOrEmpty(view.AltIcon);
			val.SetActive(flag2);
			TextMeshProUGUI component = ((Component)val.transform.Find("Alt")).GetComponent<TextMeshProUGUI>();
			if (!flag2)
			{
				((TMP_Text)component).text = "";
				foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)(ui.stamps ?? new Il2CppReferenceArray<GameObject>(0L)))
				{
					if ((Object)(object)item != (Object)null)
					{
						item.transform.position = SealHome(item.transform).position;
					}
				}
				UpdateNote(ui);
			}
			else
			{
				Place(ui, val.transform);
				Material sharedMaterial = ((Renderer)((Component)val.transform.Find("Paper")).GetComponent<MeshRenderer>()).sharedMaterial;
				Texture mainTexture = sharedMaterial.mainTexture;
				sharedMaterial.mainTexture = (Texture)(object)Compose((mainTexture != null) ? ((Il2CppObjectBase)mainTexture).TryCast<RenderTexture>() : null, view);
				((TMP_Text)component).text = (((Object)(object)view.Icon == (Object)null) ? (view.AltIcon ?? "") : "");
				((Component)val.transform.Find("Badge")).gameObject.SetActive(view.New);
				UpdateNote(ui);
			}
		}

		private static void UpdateNote(ContractUI ui)
		{
			Il2CppArrayBase<ContractUI> obj = Object.FindObjectsOfType<ContractUI>(true);
			bool flag = false;
			ContractUI anchor = ui;
			foreach (ContractUI item in obj)
			{
				if (item.IsCustom)
				{
					anchor = item;
				}
				Transform val = ((Component)item).transform.Find("TMC Contract Cosmetic");
				flag |= (Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf && ((TMP_Text)((Component)val.Find("Alt")).GetComponent<TextMeshProUGUI>()).text == "?";
			}
			if ((Object)(object)note == (Object)null)
			{
				if (!flag)
				{
					return;
				}
				note = CreateNote(anchor);
			}
			((Component)note).gameObject.SetActive(flag);
		}

		private static Transform CreateNote(ContractUI anchor)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0049: 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_002b: 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)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = anchor.infoText.transform;
			Vector3 val = ((Component)anchor).transform.right;
			if (Vector3.Dot(val, transform.forward) < 0f)
			{
				val = -val;
			}
			Vector3 val2 = Vector3.ProjectOnPlane(Vector3.up, val);
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			Vector3 val3 = Vector3.Cross(normalized, val);
			Renderer component = ((Component)anchor).GetComponent<Renderer>();
			Bounds val4 = (Bounds)(((Object)(object)component != (Object)null) ? component.bounds : new Bounds(transform.position, Vector3.one));
			float num = Extent(((Bounds)(ref val4)).size, val3);
			Vector3 val5 = ((Bounds)(ref val4)).center - normalized * (Extent(((Bounds)(ref val4)).size, normalized) / 2f);
			GameObject val6 = new GameObject("TMC Note");
			val6.transform.SetParent(((Component)anchor).transform.parent, false);
			val6.AddComponent<Canvas>().renderMode = (RenderMode)2;
			RectTransform component2 = val6.GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(400f, 110f);
			val6.transform.rotation = Quaternion.LookRotation(val, normalized);
			val6.transform.position = val5 + val3 * (num * -0.06f) - normalized * (num * 0.95f) - val * (num * 0.01f);
			float num2 = num * 1.5f / component2.sizeDelta.x;
			Vector3 lossyScale = val6.transform.parent.lossyScale;
			val6.transform.localScale = new Vector3(num2 / lossyScale.x, num2 / lossyScale.y, num2 / lossyScale.z);
			TextMeshProUGUI obj = val6.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = anchor.infoText.font;
			((TMP_Text)obj).fontSize = 28f;
			((Graphic)obj).color = new Color(0.4f, 0.37f, 0.32f, 0.85f);
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).enableWordWrapping = true;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).text = "<b>TellMeCosmetics Note:</b>\n<b><size=140%>?</size> =</b> cannot be predicted yet\nPlay that map type once to reveal it";
			return val6.transform;
		}

		private static GameObject Create(ContractUI ui)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0045: 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_0064: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("TMC Contract Cosmetic");
			val.transform.SetParent(((Component)ui).transform, false);
			val.AddComponent<Canvas>().renderMode = (RenderMode)2;
			val.AddComponent<CanvasGroup>().interactable = false;
			val.GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 114f);
			Quad(val, "Paper", Vector2.zero, new Vector2(112f, 126f), 0.05f, Lit());
			TextMeshProUGUI val2 = Text(ui, Child(val, "Alt", new Vector2(0f, 7f), new Vector2(100f, 100f)), 80f);
			((TMP_Text)val2).fontStyle = (FontStyles)1;
			((Graphic)val2).color = new Color(0.85f, 0.85f, 0.8f);
			Image obj = Child(val, "Spinner", new Vector2(0f, 7f), new Vector2(100f, 100f) * 0.45f).AddComponent<Image>();
			obj.sprite = LoadingSprite();
			((Graphic)obj).color = ((Graphic)val2).color;
			((Graphic)obj).raycastTarget = false;
			TextMeshProUGUI obj2 = Text(ui, Child(val, "Badge", BadgePos, BadgeSize), 21f);
			((TMP_Text)obj2).text = "NEW";
			((TMP_Text)obj2).fontStyle = (FontStyles)1;
			((Graphic)obj2).color = Color.white;
			return val;
		}

		private static GameObject Child(GameObject root, string name, Vector2 pos, Vector2 size)
		{
			//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)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_002c: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(root.transform, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchoredPosition = pos;
			obj.sizeDelta = size;
			return val;
		}

		private static void Quad(GameObject root, string name, Vector2 pos, Vector2 size, float z, Material mat)
		{
			//IL_0030: 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_003e: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)obj).name = name;
			Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
			obj.transform.SetParent(root.transform, false);
			obj.transform.localPosition = new Vector3(pos.x, pos.y, z);
			obj.transform.localScale = new Vector3(size.x, size.y, 1f);
			MeshRenderer component = obj.GetComponent<MeshRenderer>();
			((Renderer)component).sharedMaterial = mat;
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
		}

		private static Material Lit()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Material val = new Material(Shader.Find("HDRP/Lit"));
			val.SetFloat("_Smoothness", 0f);
			return val;
		}

		public static void Spin(ContractUI ui)
		{
			Transform val = ((Component)ui).transform.Find("TMC Contract Cosmetic/Spinner");
			if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
			{
				val.Rotate(0f, 0f, -180f * Time.deltaTime, (Space)1);
			}
		}

		private static Sprite LoadingSprite()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Expected O, but got Unknown
			if ((Object)(object)loadingSprite != (Object)null || loadingTried)
			{
				return loadingSprite;
			}
			loadingTried = true;
			try
			{
				string unityGameDataDirectory = MelonEnvironment.UnityGameDataDirectory;
				AssetsManager val = new AssetsManager();
				AssetsFileInstance val2 = val.LoadAssetsFile(Path.Combine(unityGameDataDirectory, "sharedassets3.assets"), false);
				try
				{
					AssetsFileReader reader = val2.file.Reader;
					foreach (AssetFileInfo item in val2.file.GetAssetsOfType((AssetClassID)28))
					{
						reader.Position = item.GetAbsoluteByteOffset(val2.file);
						byte[] array = ((BinaryReader)(object)reader).ReadBytes((int)item.ByteSize);
						int num = BitConverter.ToInt32(array, 0);
						if (num != "Circle Dash 2 64px - Stroke 10px".Length || Encoding.UTF8.GetString(array, 4, num) != "Circle Dash 2 64px - Stroke 10px")
						{
							continue;
						}
						int num2 = 4 + (num + 3) / 4 * 4 + 8;
						int num3 = BitConverter.ToInt32(array, num2);
						int num4 = BitConverter.ToInt32(array, num2 + 4);
						int num5 = BitConverter.ToInt32(array, num2 + 16);
						byte[] bytes = Encoding.ASCII.GetBytes("sharedassets3.assets.resS");
						int num6 = array.AsSpan().LastIndexOf(bytes);
						if (num6 < 16)
						{
							return null;
						}
						long position = BitConverter.ToInt64(array, num6 - 16);
						int num7 = BitConverter.ToInt32(array, num6 - 8);
						byte[] array2 = new byte[num7];
						using (FileStream fileStream = File.OpenRead(Path.Combine(unityGameDataDirectory, "sharedassets3.assets.resS")))
						{
							fileStream.Position = position;
							int num8;
							for (int i = 0; i < num7; i += num8)
							{
								if ((num8 = fileStream.Read(array2, i, num7 - i)) <= 0)
								{
									throw new EndOfStreamException();
								}
							}
						}
						Texture2D val3 = new Texture2D(num3, num4, (TextureFormat)num5, false)
						{
							hideFlags = (HideFlags)32
						};
						val3.LoadRawTextureData(Il2CppStructArray<byte>.op_Implicit(array2));
						val3.Apply(false, true);
						loadingSprite = Sprite.Create(val3, new Rect(0f, 0f, (float)num3, (float)num4), new Vector2(0.5f, 0.5f));
						((Object)loadingSprite).hideFlags = (HideFlags)32;
						return loadingSprite;
					}
				}
				finally
				{
					val.UnloadAll(false);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Loading icon not read: " + ex.Message);
			}
			return null;
		}

		private static RenderTexture Compose(RenderTexture rt, View view)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			int num = 224;
			int num2 = 252;
			if (rt == null)
			{
				rt = new RenderTexture(num, num2, 0);
			}
			RenderTexture active = RenderTexture.active;
			RenderTexture.active = rt;
			GL.PushMatrix();
			GL.LoadPixelMatrix(0f, (float)num, (float)num2, 0f);
			GL.Clear(true, true, Color.clear);
			Graphics.DrawTexture(new Rect(0f, 0f, (float)num, (float)num2), (Texture)(object)PaperTexture());
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(12f, 12f, 200f, 200f);
			Graphics.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), 0, 0, 0, 0, new Color(0f, 0f, 0f, 0.5f));
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.5f, 0.5f, 0.5f, 0.5f);
			if (!view.Silhouette && (Object)(object)view.Frame != (Object)null)
			{
				Texture2D texture = view.Frame.texture;
				Rect textureRect = view.Frame.textureRect;
				Graphics.DrawTexture(val, (Texture)(object)texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height), 0, 0, 0, 0, view.FrameColor * 0.5f);
			}
			DrawSprite(view.Icon, val, 0.8f, view.Silhouette ? Color.white : val2, view.Silhouette ? SilhouetteMaterial() : null);
			if (view.New)
			{
				Vector2 val3 = new Vector2(56f + BadgePos.x, 63f - BadgePos.y) * 2f;
				Vector2 val4 = BadgeSize * 2f;
				Graphics.DrawTexture(new Rect(val3 - val4 / 2f, val4), (Texture)(object)Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), 0, 0, 0, 0, new Color(0.45f, 0.06f, 0.05f, 0.5f));
			}
			GL.PopMatrix();
			RenderTexture.active = active;
			return rt;
		}

		private static void DrawSprite(Sprite sprite, Rect area, float fill, Color tint, Material mat = null)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)sprite == (Object)null))
			{
				Texture2D texture = sprite.texture;
				Rect textureRect = sprite.textureRect;
				float num = Mathf.Min(((Rect)(ref area)).width, ((Rect)(ref area)).height) * fill;
				float num2 = ((((Rect)(ref textureRect)).width >= ((Rect)(ref textureRect)).height) ? num : (num * ((Rect)(ref textureRect)).width / ((Rect)(ref textureRect)).height));
				float num3 = ((((Rect)(ref textureRect)).width >= ((Rect)(ref textureRect)).height) ? (num * ((Rect)(ref textureRect)).height / ((Rect)(ref textureRect)).width) : num);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height);
				Graphics.DrawTexture(new Rect(((Rect)(ref area)).center.x - num2 / 2f, ((Rect)(ref area)).center.y - num3 / 2f, num2, num3), (Texture)(object)texture, val, 0, 0, 0, 0, tint, mat);
			}
		}

		internal static Material SilhouetteMaterial()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if ((Object)(object)silhouette != (Object)null)
			{
				return silhouette;
			}
			silhouette = new Material(Shader.Find("GUI/Text Shader"))
			{
				color = Color.white
			};
			((Object)silhouette).hideFlags = (HideFlags)32;
			return silhouette;
		}

		private static TextMeshProUGUI Text(ContractUI ui, GameObject go, float size)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI obj = go.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = ui.infoText.font;
			((Graphic)obj).color = new Color(0.12f, 0.1f, 0.08f);
			((TMP_Text)obj).fontMaterial.SetColor("_FaceColor", Color.white);
			((TMP_Text)obj).fontSize = size;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).enableWordWrapping = true;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private static void Place(ContractUI ui, Transform root)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ui.infoText.transform;
			Vector3 right = transform.right;
			Vector3 up = transform.up;
			Vector3 forward = transform.forward;
			object obj;
			if (ui.photoMeshFilters == null || ((Il2CppArrayBase<MeshFilter>)(object)ui.photoMeshFilters).Length <= 0)
			{
				obj = null;
			}
			else
			{
				MeshFilter obj2 = ((Il2CppArrayBase<MeshFilter>)(object)ui.photoMeshFilters)[0];
				obj = ((obj2 != null) ? ((Component)obj2).GetComponent<Renderer>() : null);
			}
			Renderer val = (Renderer)obj;
			float num;
			Vector3 val2;
			if ((Object)(object)val != (Object)null)
			{
				Bounds bounds = val.bounds;
				num = Extent(((Bounds)(ref bounds)).size, right);
				val2 = ((Bounds)(ref bounds)).center - up * (Extent(((Bounds)(ref bounds)).size, up) / 2f);
			}
			else
			{
				Rect rect = ui.infoText.rectTransform.rect;
				num = ((Rect)(ref rect)).width * transform.lossyScale.x;
				val2 = transform.position - up * num;
			}
			float num2 = num * 0.55f / 100f;
			float num3 = 114f * num2;
			Vector3 val3 = val2 - up * (num3 / 2f + num * 0.01f);
			Renderer val4 = Seal(ui, transform.position, forward);
			if ((Object)(object)val4 == (Object)null)
			{
				root.rotation = transform.rotation;
				root.position = val3 - forward * num * 0.002f;
			}
			else
			{
				Transform transform2 = ((Component)val4).transform;
				Vector3 position = SealHome(transform2).position;
				Bounds bounds2 = val4.bounds;
				Vector3 val5 = position + (((Bounds)(ref bounds2)).center - transform2.position);
				Vector3 val6 = ((Component)ui).transform.right;
				if (Vector3.Dot(val6, forward) < 0f)
				{
					val6 = -val6;
				}
				Vector3 val7 = Vector3.ProjectOnPlane(up, val6);
				Vector3 normalized = ((Vector3)(ref val7)).normalized;
				root.rotation = Quaternion.LookRotation(val6, normalized);
				float num4 = Vector3.Dot(val3 - val5, normalized) - num3 / 2f;
				if (num4 > 0f)
				{
					val3 -= normalized * num4;
				}
				root.position = val3 - val6 * (Vector3.Dot(val3 - val5, val6) + num * 0.06f);
				bounds2 = val4.bounds;
				float num5 = Extent(((Bounds)(ref bounds2)).size, val6) / 2f;
				Vector3 position2 = transform2.position;
				Vector3 val8 = val5 - val6 * (Vector3.Dot(val5 - root.position, val6) + num5 + num * 0.002f);
				bounds2 = val4.bounds;
				transform2.position = position2 + (val8 - ((Bounds)(ref bounds2)).center);
			}
			Vector3 lossyScale = root.parent.lossyScale;
			root.localScale = new Vector3(num2 / lossyScale.x, num2 / lossyScale.y, num2 / lossyScale.z);
		}

		private static Texture2D PaperTexture()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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)
			//IL_002e: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)paperTexture != (Object)null)
			{
				return paperTexture;
			}
			Texture2D val = new Texture2D(108, 128)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Random random = new Random(1234);
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 108; j++)
				{
					float num = (Mathf.PerlinNoise((float)j * 0.05f, (float)i * 0.35f) - 0.5f) * 0.06f + (Mathf.PerlinNoise((float)j * 0.2f, (float)i * 0.2f) - 0.5f) * 0.04f;
					float num2 = ((float)random.NextDouble() - 0.5f) * 0.03f;
					int num3 = Mathf.Min(Mathf.Min(j, 107 - j), Mathf.Min(i, 127 - i));
					float num4 = ((num3 < 7) ? ((float)(7 - num3) / 7f * 0.12f) : 0f);
					float num5 = 1f + num + num2 - num4;
					val.SetPixel(j, i, new Color(0.94f * num5, 0.91f * num5, 0.82f * num5, 1f));
				}
			}
			val.Apply();
			((Object)val).hideFlags = (HideFlags)32;
			return paperTexture = val;
		}

		private static Transform SealHome(Transform seal)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			string text = "TMC Seal Home " + ((Object)seal).name;
			Transform val = seal.parent.Find(text);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = new GameObject(text).transform;
			val.SetParent(seal.parent, false);
			val.position = seal.position;
			return val;
		}

		private static Renderer Seal(ContractUI ui, Vector3 plane, Vector3 forward)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MinValue;
			Renderer result = null;
			foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)(ui.stamps ?? new Il2CppReferenceArray<GameObject>(0L)))
			{
				if (!((Object)(object)item != (Object)null) || !item.activeInHierarchy)
				{
					continue;
				}
				foreach (Renderer componentsInChild in item.GetComponentsInChildren<Renderer>())
				{
					Bounds bounds = componentsInChild.bounds;
					float num2 = Vector3.Dot(((Bounds)(ref bounds)).center - plane, -forward) + Extent(((Bounds)(ref bounds)).size, forward) / 2f;
					if (!(num2 <= num))
					{
						num = num2;
						result = componentsInChild;
					}
				}
			}
			return result;
		}

		private static float Extent(Vector3 size, Vector3 axis)
		{
			//IL_0000: 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)
			//IL_0012: 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)
			return Mathf.Abs(size.x * axis.x) + Mathf.Abs(size.y * axis.y) + Mathf.Abs(size.z * axis.z);
		}
	}
	public class ItemAlertUI
	{
		private static readonly string TAG = "ItemAlert UI";

		private readonly CustomizationItem[] itemsCollection;

		private readonly TMP_FontAsset fontref;

		private readonly GameObject ui_object;

		private readonly TextMeshProUGUI myText;

		private readonly GameObject iconObject;

		private readonly Image iconImage;

		private readonly GameObject iconAltObject;

		private readonly TextMeshProUGUI iconAltImage;

		private ushort itemID;

		public ItemAlertUI(RectTransform parentUI, ItemsCollectionSO itemsCollectionSO)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Expected O, but got Unknown
			fontref = UIUtils.GetFontByName("Larke Sans Regular SDF");
			itemsCollection = Il2CppArrayBase<CustomizationItem>.op_Implicit((Il2CppArrayBase<CustomizationItem>)(object)((itemsCollectionSO != null) ? itemsCollectionSO.collection : null));
			MelonLogger.Msg($"Loaded {itemsCollection.Length} cosmetic assets!");
			ui_object = new GameObject(TAG);
			ui_object.SetActive(false);
			ui_object.transform.SetParent((Transform)(object)parentUI, false);
			RectTransform obj = ui_object.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 0f);
			obj.anchorMax = new Vector2(0f, 0f);
			obj.pivot = new Vector2(0f, 0f);
			obj.anchoredPosition = new Vector2(0f, 0f);
			obj.sizeDelta = new Vector2(0f, 50f);
			HorizontalLayoutGroup obj2 = ui_object.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj2).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 10f;
			iconObject = new GameObject("Item Icon");
			iconObject.transform.SetParent(ui_object.transform, false);
			iconObject.SetActive(false);
			iconImage = iconObject.AddComponent<Image>();
			iconImage.preserveAspect = true;
			iconImage.sprite = null;
			iconObject.GetComponent<RectTransform>().sizeDelta = new Vector2(64f, 64f);
			iconAltObject = new GameObject("Item Icon Alt");
			iconAltObject.transform.SetParent(ui_object.transform, false);
			iconAltObject.SetActive(false);
			iconAltImage = iconAltObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)iconAltImage).font = fontref;
			((TMP_Text)iconAltImage).fontSize = 60f;
			((TMP_Text)iconAltImage).richText = false;
			((TMP_Text)iconAltImage).fontWeight = (FontWeight)900;
			((TMP_Text)iconAltImage).alignment = (TextAlignmentOptions)4098;
			iconAltObject.GetComponent<RectTransform>().sizeDelta = new Vector2(64f, 64f);
			GameObject val = new GameObject("Item Name");
			val.transform.SetParent(ui_object.transform, false);
			myText = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)myText).font = fontref;
			((TMP_Text)myText).fontSize = 36f;
			((TMP_Text)myText).richText = false;
			((TMP_Text)myText).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)myText).overflowMode = (TextOverflowModes)0;
		}

		private void SetItemUI(string itemText, Sprite icon = null, char altIcon = '?', bool silhouette = false)
		{
			((TMP_Text)myText).text = itemText;
			((TMP_Text)myText).fontStyle = (FontStyles)0;
			iconImage.sprite = icon;
			((Graphic)iconImage).material = (silhouette ? ContractItemUI.SilhouetteMaterial() : null);
			iconObject.SetActive((Object)(object)icon != (Object)null);
			((TMP_Text)iconAltImage).text = (((Object)(object)icon == (Object)null) ? altIcon.ToString() : string.Empty);
			iconAltObject.SetActive((Object)(object)icon == (Object)null);
			ui_object.SetActive(true);
		}

		public void Show(CustomizationPickup item, bool reveal = true)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Invalid comparison between Unknown and I4
			itemID = item.ItemID;
			if ((Object)(object)ui_object == (Object)null || (Object)(object)myText == (Object)null || (Object)(object)iconImage == (Object)null)
			{
				return;
			}
			if (itemsCollection != null && itemID < itemsCollection.Length)
			{
				CustomizationItem val = itemsCollection[itemID];
				string itemText = (reveal ? Describe(val, itemID) : "Undiscovered Item");
				if ((int)val.BodyPart == 100)
				{
					SetItemUI(itemText, null, '♫');
				}
				else
				{
					SetItemUI(itemText, val.Icon, '?', !reveal);
				}
			}
			else
			{
				SetItemUI(reveal ? $"#{itemID} {FilterClone(((Object)item).name)}" : "Undiscovered Item");
			}
		}

		internal static string Describe(CustomizationItem itemData, ushort itemID)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			return $"#{itemID} " + ((!string.IsNullOrEmpty(itemData.Name)) ? itemData.Name : ((Object)itemData.icon).name).Replace("_", " ") + " " + $"({itemData.ItemRarity})";
		}

		public void Pickup(ushort itemID)
		{
			if (this.itemID == itemID)
			{
				MelonLogger.Msg("Picked item up");
				((TMP_Text)myText).fontStyle = (FontStyles)64;
			}
		}

		public void Clear()
		{
			if (!((Object)(object)ui_object == (Object)null) && !((Object)(object)myText == (Object)null))
			{
				ui_object.SetActive(false);
				((TMP_Text)myText).text = string.Empty;
				((TMP_Text)myText).fontStyle = (FontStyles)0;
				iconImage.sprite = null;
				iconObject.SetActive(false);
				((TMP_Text)iconAltImage).text = string.Empty;
				iconAltObject.SetActive(false);
			}
		}

		public bool IsDestroy()
		{
			return (Object)(object)ui_object == (Object)null;
		}

		private static string FilterClone(string name)
		{
			if (name.EndsWith("(Clone)"))
			{
				int length = "(Clone)".Length;
				return name.Substring(0, name.Length - length).Replace("_", " ");
			}
			return name;
		}
	}
	public static class UIUtils
	{
		public static TMP_FontAsset GetFontByName(string name)
		{
			return ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name.Equals(name, StringComparison.OrdinalIgnoreCase)));
		}
	}
}
namespace TellMeCosmetics.Predict
{
	public static class ContractPredictor
	{
		public record Entry(int Id, float W);

		public record Seasonal(int Type, float Chance, Entry[] Prefabs);

		public record Pool(float[] Chance, Entry[] Normal, Entry[] Hardcore, Seasonal[] Seasonal);

		private const int Hardcore = 2;

		private static readonly ConcurrentDictionary<int, Pool> pools = new ConcurrentDictionary<int, Pool>();

		private static readonly Dictionary<(int, int, int, int, int), Task<MazePipeline.Outcome>> outcomes = new Dictionary<(int, int, int, int, int), Task<MazePipeline.Outcome>>();

		private static string CachePath(int mazeType)
		{
			return Path.Combine(MelonEnvironment.UserDataDirectory, "TellMeCosmetics", $"pool.{mazeType}.txt");
		}

		internal static Pool GetPool(int mazeType)
		{
			return pools.GetOrAdd(mazeType, LoadCache);
		}

		internal static void StoreIfMissing(int mazeType, Pool pool)
		{
			if (!(GetPool(mazeType) != null))
			{
				pools[mazeType] = pool;
				SaveCache(mazeType, pool);
			}
		}

		private static Pool LoadCache(int mazeType)
		{
			try
			{
				string path = CachePath(mazeType);
				if (!File.Exists(path))
				{
					return null;
				}
				return Parse(File.ReadAllLines(path), ScenePreload.Stamp);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Pool cache unreadable: " + ex.Message);
				return null;
			}
		}

		internal static Pool Parse(string[] l, string stamp)
		{
			if (l.Length < 4 || l[0] != "v " + stamp)
			{
				return null;
			}
			l = l[1..];
			return new Pool(Split(l[0]).Select(F).ToArray(), Entries(Split(l[1])), Entries(Split(l[2])), (from t in l.Skip(3).Select(Split)
				select new Seasonal(int.Parse(t[0]), F(t[1]), Entries(t[2..]))).ToArray());
		}

		internal static string[] FileLines(Pool pool, string stamp)
		{
			return Lines(pool).Prepend("v " + stamp).ToArray();
		}

		private static string[] Split(string line)
		{
			return line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
		}

		private static float F(string v)
		{
			return float.Parse(v, CultureInfo.InvariantCulture);
		}

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

		private static Entry[] Entries(string[] t)
		{
			return (from x in t
				select x.Split(':') into x
				select new Entry(int.Parse(x[0]), F(x[1]))).ToArray();
		}

		private static string Line(Entry[] e)
		{
			return string.Join(" ", e.Select((Entry x) => $"{x.Id}:{S(x.W)}"));
		}

		internal static string[] Lines(Pool pool)
		{
			return new string[3]
			{
				string.Join(" ", pool.Chance.Select(S)),
				Line(pool.Normal),
				Line(pool.Hardcore)
			}.Concat(pool.Seasonal.Select((Seasonal c) => $"{c.Type} {S(c.Chance)} {Line(c.Prefabs)}")).ToArray();
		}

		private static void SaveCache(int mazeType, Pool pool)
		{
			string[] contents = FileLines(pool, ScenePreload.Stamp);
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(CachePath(mazeType)));
				File.WriteAllLines(CachePath(mazeType), contents);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Pool cache not saved: " + ex.Message);
			}
		}

		private static Entry[] ToEntries(IEnumerable<WeightedPrefab> list)
		{
			CustomizationPickup val = default(CustomizationPickup);
			return list?.Select((WeightedPrefab p) => new Entry(((Object)(object)((ValueWithWeight<GameObject>)(object)p).Value != (Object)null && ((ValueWithWeight<GameObject>)(object)p).Value.TryGetComponent<CustomizationPickup>(ref val)) ? val.ItemID : (-1), ((ValueWithWeight<GameObject>)(object)p).weight)).ToArray() ?? Array.Empty<Entry>();
		}

		private static Entry[] SpawnerPool(RndCustomizationSpawner s, bool hardcore)
		{
			return ToEntries((IEnumerable<WeightedPrefab>)((!hardcore) ? ((ReadOnlyScriptableValue<Il2CppReferenceArray<WeightedPrefab>>)(object)s.globalPrefabs)?.Value : ((ReadOnlyScriptableValue<Il2CppReferenceArray<WeightedPrefab>>)(object)s.globalPrefabsHardcore)?.Value)).Concat(ToEntries((IEnumerable<WeightedPrefab>)(hardcore ? s.possiblePrefabsHardcore : s.possiblePrefabs))).ToArray();
		}

		public static Pool Capture(RndCustomizationItemsManager mgr, int mazeType)
		{
			Il2CppArrayBase<RndCustomizationSpawner> val = Object.FindObjectsOfType<RndCustomizationSpawner>();
			if ((Object)(object)mgr == (Object)null || val.Length == 0)
			{
				return null;
			}
			Entry[] normal = SpawnerPool(val[0], hardcore: false);
			if (((IEnumerable<RndCustomizationSpawner>)val).Any((RndCustomizationSpawner s) => !((ReadOnlySpan<Entry>)SpawnerPool(s, hardcore: false)).SequenceEqual((ReadOnlySpan<Entry>)normal)))
			{
				MelonLogger.Warning("RndCustomizationSpawners have different pools; lobby prediction may be wrong for this maze.");
			}
			Pool pool = (pools[mazeType] = new Pool(((IEnumerable<float>)mgr.chanceForItem).ToArray(), normal, SpawnerPool(val[0], hardcore: true), (from c in ((IEnumerable<SeasonalItemsConfig>)mgr.seasonalItems).ToArray()
				where c != null
				select new Seasonal((int)c.seasonalEventType, c.chance, ToEntries((IEnumerable<WeightedPrefab>)c.prefabs))).ToArray()));
			Pool pool3 = pool;
			SaveCache(mazeType, pool3);
			return pool3;
		}

		private static Entry Pick(NetRandom rnd, Entry[] list)
		{
			if (list.Length == 0)
			{
				return null;
			}
			double num = 0.0;
			double num2 = 0.0;
			Entry[] array = list;
			foreach (Entry entry in array)
			{
				num += (double)entry.W;
			}
			double num3 = rnd.NextDouble() * num;
			array = list;
			foreach (Entry entry2 in array)
			{
				if ((double)entry2.W + num2 >= num3)
				{
					return entry2;
				}
				num2 += (double)entry2.W;
			}
			return list[^1];
		}

		public static MazePipeline.ContractInput ToInput(Contract c)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected I4, but got Unknown
			//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)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected I4, but got Unknown
			MazePipeline.ContractInput obj = new MazePipeline.ContractInput
			{
				Seed = c.Seed,
				SecondSeed = c.SecondSeed,
				MazeType = (int)c.MazeType
			};
			Vector2Int mapSizeVec = c.MapSizeVec;
			obj.MapX = ((Vector2Int)(ref mapSizeVec)).x;
			mapSizeVec = c.MapSizeVec;
			obj.MapY = ((Vector2Int)(ref mapSizeVec)).y;
			obj.MapSize = (int)c.MapSize;
			obj.LandmarkCount = c.LandmarkCount;
			obj.PuzzleCount = c.PuzzleCount;
			return obj;
		}

		public static void ClearOutcomes()
		{
			outcomes.Clear();
		}

		public static (int seed, int second, bool simulated) MazeSeeds(Contract contract)
		{
			bool pending;
			return MazeSeeds(contract, wait: true, out pending);
		}

		public static (int seed, int second, bool simulated) MazeSeeds(Contract contract, bool wait, out bool pending)
		{
			pending = false;
			MazePipeline.ContractInput input = ToInput(contract);
			MazePipeline.Config cfg = MazePipeline.Get(input.MazeType);
			if (cfg == null)
			{
				return (seed: input.Seed, second: input.SecondSeed, simulated: false);
			}
			if (ConfigManager.Instance.DebugPerfTest.Value)
			{
				PredictPerfTest.BenchOnce(cfg, input);
			}
			(int, int, int, int, int) key = (input.Seed, input.SecondSeed, input.MazeType, input.MapX, input.MapY);
			if (!outcomes.TryGetValue(key, out var value))
			{
				value = (outcomes[key] = Task.Run(delegate
				{
					try
					{
						return MazePipeline.Simulate(cfg, input);
					}
					catch (Exception value2)
					{
						MelonLogger.Warning($"Maze simulation failed: {value2}");
						return (MazePipeline.Outcome)null;
					}
				}));
			}
			if (!wait && !value.IsCompleted)
			{
				pending = true;
				return (seed: input.Seed, second: input.SecondSeed, simulated: false);
			}
			MazePipeline.Outcome result = value.Result;
			if (result != null)
			{
				return (seed: result.Seed, second: result.SecondSeed, simulated: true);
			}
			return (seed: input.Seed, second: input.SecondSeed, simulated: false);
		}

		public static int? Predict(Contract contract, out float chance, out bool simulated)
		{
			bool pending;
			return Predict(contract, wait: true, out chance, out simulated, out pending);
		}

		public static int? Predict(Contract contract, bool wait, out float chance, out bool simulated, out bool pending)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected I4, but got Unknown
			chance = 0f;
			simulated = false;
			pending = false;
			Pool pool = GetPool((int)contract.MazeType);
			if (pool == null)
			{
				return null;
			}
			var (num, num2, flag) = MazeSeeds(contract, wait, out pending);
			if (pending)
			{
				return null;
			}
			simulated = flag;
			int num3 = (int)contract.ContractType;
			if (num3 >= pool.Chance.Length)
			{
				return null;
			}
			chance = pool.Chance[num3];
			if (!((double)chance > new NetRandom(num2).NextDouble()))
			{
				return null;
			}
			Entry[] array = null;
			ISeasonalEvent evt = default(ISeasonalEvent);
			TimeSpan val = default(TimeSpan);
			DateTimeOffset val2 = default(DateTimeOffset);
			if (num3 != 2 && SeasonalEventsTimeHandler.TryGetActiveSeasonalEvent(ref evt, ref val, ref val2) && evt != null)
			{
				Seasonal seasonal = pool.Seasonal.FirstOrDefault((Seasonal c) => c.Prefabs.Length != 0 && c.Type == (int)evt.EventType);
				if (seasonal != null && (double)seasonal.Chance > new NetRandom(num2 + 4789).NextDouble())
				{
					array = seasonal.Prefabs;
				}
			}
			if (array == null)
			{
				array = ((num3 == 2) ? pool.Hardcore : pool.Normal);
			}
			List<ushort> excluded = contract.m_ExcludedCustomizationItemIDs;
			NetRandom rnd = new NetRandom((num2 + 9187 + num + 1682) / 2);
			for (int num4 = 0; num4 < 50; num4++)
			{
				Entry entry = Pick(rnd, array);
				if (ok(entry))
				{
					return entry.Id;
				}
			}
			Entry entry2 = array.FirstOrDefault(ok) ?? Pick(rnd, array);
			if (!(entry2 != null) || entry2.Id < 0)
			{
				return null;
			}
			return entry2.Id;
			bool ok(Entry e)
			{
				if (e != null && e.Id >= 0)
				{
					return !(excluded?.Contains((ushort)e.Id) ?? false);
				}
				return false;
			}
		}
	}
	public sealed class NetRandom
	{
		private const int MBIG = int.MaxValue;

		private const int MSEED = 161803398;

		internal readonly int[] _seedArray = new int[56];

		internal int _inext;

		internal int _inextp;

		public NetRandom(int seed)
		{
			int num = 161803398 - ((seed == int.MinValue) ? int.MaxValue : Math.Abs(seed));
			int num2 = 1;
			_seedArray[55] = num;
			for (int i = 1; i < 55; i++)
			{
				int num3 = 21 * i % 55;
				_seedArray[num3] = num2;
				num2 = num - num2;
				if (num2 < 0)
				{
					num2 += int.MaxValue;
				}
				num = _seedArray[num3];
			}
			for (int j = 1; j < 5; j++)
			{
				for (int k = 1; k < 56; k++)
				{
					_seedArray[k] -= _seedArray[1 + (k + 30) % 55];
					if (_seedArray[k] < 0)
					{
						_seedArray[k] += int.MaxValue;
					}
				}
			}
			_inext = 0;
			_inextp = 21;
		}

		internal NetRandom(int[] seedArray, int inext, int inextp)
		{
			seedArray.CopyTo(_seedArray, 0);
			_inext = inext;
			_inextp = inextp;
		}

		private int InternalSample()
		{
			if (++_inext >= 56)
			{
				_inext = 1;
			}
			if (++_inextp >= 56)
			{
				_inextp = 1;
			}
			int num = _seedArray[_inext] - _seedArray[_inextp];
			if (num == int.MaxValue)
			{
				num--;
			}
			if (num < 0)
			{
				num += int.MaxValue;
			}
			_seedArray[_inext] = num;
			return num;
		}

		private double Sample()
		{
			return (double)InternalSample() * 4.656612875245797E-10;
		}

		public int Next()
		{
			return InternalSample();
		}

		public double NextDouble()
		{
			return Sample();
		}

		public int Next(int maxValue)
		{
			if (maxValue < 0)
			{
				throw new ArgumentOutOfRangeException("maxValue");
			}
			return (int)(Sample() * (double)maxValue);
		}

		public int Next(int minValue, int maxValue)
		{
			if (minValue > maxValue)
			{
				throw new ArgumentOutOfRangeException("minValue");
			}
			long num = (long)maxValue - (long)minValue;
			if (num <= int.MaxValue)
			{
				return (int)(Sample() * (double)num) + minValue;
			}
			int num2 = InternalSample();
			if (InternalSample() % 2 == 0)
			{
				num2 = -num2;
			}
			return (int)((long)(((double)num2 + 2147483646.0) / 4294967293.0 * (double)num) + minValue);
		}
	}
	public sealed class UnityRandom
	{
		internal uint s0;

		internal uint s1;

		internal uint s2;

		internal uint s3;

		public float Value => (float)(NextUInt() & 0x7FFFFF) * 1.192093E-07f;

		public UnityRandom(int seed)
		{
			s0 = (uint)seed;
			s1 = s0 * 1812433253 + 1;
			s2 = s1 * 1812433253 + 1;
			s3 = s2 * 1812433253 + 1;
		}

		private uint NextUInt()
		{
			uint num = s0 ^ (s0 << 11);
			s0 = s1;
			s1 = s2;
			s2 = s3;
			s3 = s3 ^ (s3 >> 19) ^ num ^ (num >> 8);
			return s3;
		}
	}
	internal static class GameRandomTest
	{
		public static void Run()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: 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)
			//IL_0033: Expected O, but got Unknown
			int num = 0;
			int[] array = new int[8] { 0, 1, -1, 12345, 2147483647, -2147483648, 1187, -987654321 };
			State state = Random.state;
			try
			{
				int[] array2 = array;
				foreach (int num2 in array2)
				{
					Random val = new Random(num2);
					NetRandom netRandom = new NetRandom(num2);
					for (int j = 0; j < 500; j++)
					{
						if ((j % 5) switch
						{
							0 => (val.Next() == netRandom.Next()) ? 1 : 0, 
							1 => (val.NextDouble() == netRandom.NextDouble()) ? 1 : 0, 
							2 => (val.Next(j + 1) == netRandom.Next(j + 1)) ? 1 : 0, 
							3 => (val.Next(-j, 3 * j) == netRandom.Next(-j, 3 * j)) ? 1 : 0, 
							_ => (val.Next(int.MinValue + j, int.MaxValue - j) == netRandom.Next(int.MinValue + j, int.MaxValue - j)) ? 1 : 0, 
						} == 0 && num++ == 0)
						{
							MelonLogger.Msg($"\ud83e\uddeaGameRandom NetRandom first diff seed={num2} call={j}");
						}
					}
					Random.InitState(num2);
					UnityRandom unityRandom = new UnityRandom(num2);
					for (int k = 0; k < 500; k++)
					{
						if (Random.value != unityRandom.Value && num++ == 0)
						{
							MelonLogger.Msg($"\ud83e\uddeaGameRandom UnityRandom first diff seed={num2} call={k}");
						}
					}
				}
			}
			finally
			{
				Random.state = state;
			}
			MelonLogger.Msg("\ud83e\uddeaGameRandom " + ((num == 0) ? "MATCH" : $"MISMATCH diffs={num}"));
		}
	}
	internal sealed class Il2CppLayouts : ScenePreload.LayoutSource
	{
		private const int FieldStatic = 16;

		private const int FieldInitOnly = 32;

		private const int FieldLiteral = 64;

		private const int FieldNotSerialized = 128;

		private const int FieldAccessMask = 7;

		private const int FieldPublic = 6;

		private const int TypeInterface = 32;

		private const int TypeAbstract = 128;

		private const int TypeSerializable = 8192;

		private readonly IntPtr unityObject = IL2CPP.GetIl2CppClass("UnityEngine.CoreModule.dll", "UnityEngine", "Object");

		private readonly IntPtr serializeField = IL2CPP.GetIl2CppClass("UnityEngine.CoreModule.dll", "UnityEngine", "SerializeField");

		private readonly IntPtr serializeReference = IL2CPP.GetIl2CppClass("UnityEngine.CoreModule.dll", "UnityEngine", "SerializeReference");

		private static IntPtr K(object t)
		{
			return (IntPtr)t;
		}

		private static object Box(IntPtr p)
		{
			if (!(p == IntPtr.Zero))
			{
				return p;
			}
			return null;
		}

		private static object TypeClass(IntPtr il2cppType)
		{
			if (!(il2cppType == IntPtr.Zero))
			{
				return Box(IL2CPP.il2cpp_class_from_il2cpp_type(il2cppType));
			}
			return null;
		}

		protected override object FindClass(string assembly, string ns, string name)
		{
			return Box(IL2CPP.GetIl2CppClass(assembly.EndsWith(".dll") ? assembly : (assembly + ".dll"), ns, name));
		}

		protected override string FullName(object t)
		{
			string text = IL2CPP.il2cpp_class_get_namespace_(K(t));
			string text2 = IL2CPP.il2cpp_class_get_name_(K(t));
			if (!string.IsNullOrEmpty(text))
			{
				return text + "." + text2;
			}
			return text2;
		}

		protected override object ArrayElement(object t)
		{
			IntPtr intPtr = K(t);
			if (IL2CPP.il2cpp_class_get_rank(intPtr) == 1)
			{
				return Box(IL2CPP.il2cpp_class_get_element_class(intPtr));
			}
			if (FullName(t) != "System.Collections.Generic.List`1")
			{
				return null;
			}
			foreach (IntPtr item in Fields(intPtr))
			{
				if (IL2CPP.il2cpp_field_get_name_(item) == "_items")
				{
					return Box(IL2CPP.il2cpp_class_get_element_class(K(TypeClass(IL2CPP.il2cpp_field_get_type(item)))));
				}
			}
			return null;
		}

		protected override object EnumUnderlying(object t)
		{
			if (!IL2CPP.il2cpp_class_is_enum(K(t)))
			{
				return null;
			}
			return TypeClass(IL2CPP.il2cpp_class_enum_basetype(K(t)));
		}

		protected override bool IsUnityObject(object t)
		{
			if (!(K(t) == unityObject))
			{
				return IL2CPP.il2cpp_class_is_subclass_of(K(t), unityObject, false);
			}
			return true;
		}

		protected override bool IsSerializableClass(object t)
		{
			int num = IL2CPP.il2cpp_class_get_flags(K(t));
			if ((num & 0x2000) != 0 && (num & 0xA0) == 0)
			{
				return !FullName(t).StartsWith("System.");
			}
			return false;
		}

		protected override IEnumerable<FieldInfo> SerializedFields(object t)
		{
			List<IntPtr> list = new List<IntPtr>();
			IntPtr intPtr = K(t);
			while (intPtr != IntPtr.Zero)
			{
				bool flag;
				switch (FullName(intPtr))
				{
				case "UnityEngine.MonoBehaviour":
				case "UnityEngine.ScriptableObject":
				case "UnityEngine.Object":
				case "System.Object":
				case "System.ValueType":
					flag = true;
					break;
				default:
					flag = false;
					break;
				}
				if (flag)
				{
					break;
				}
				list.Insert(0, intPtr);
				intPtr = IL2CPP.il2cpp_class_get_parent(intPtr);
			}
			foreach (IntPtr item in list)
			{
				foreach (IntPtr item2 in Fields(item))
				{
					int num = IL2CPP.il2cpp_field_get_flags(item2);
					if ((num & 0x70) == 0)
					{
						bool flag2 = serializeReference != IntPtr.Zero && IL2CPP.il2cpp_field_has_attribute(item2, serializeReference);
						bool num2 = flag2 || IL2CPP.il2cpp_field_has_attribute(item2, serializeField) || ((num & 7) == 6 && (num & 0x80) == 0);
						object obj = TypeClass(IL2CPP.il2cpp_field_get_type(item2));
						if (num2 && obj != null)
						{
							yield return new FieldInfo(IL2CPP.il2cpp_field_get_name_(item2), obj, flag2);
						}
					}
				}
			}
		}

		private static IEnumerable<IntPtr> Fields(IntPtr k)
		{
			IntPtr iter = IntPtr.Zero;
			IntPtr intPtr;
			while ((intPtr = IL2CPP.il2cpp_class_get_fields(k, ref iter)) != IntPtr.Zero)
			{
				yield return intPtr;
			}
		}
	}
	[HarmonyPatch(typeof(MazeGenerator), "GenerateMap")]
	internal class MazeCapture
	{
		private static void Prefix(MazeGenerator __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected I4, but got Unknown
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Contract contract = __instance.contract;
				RndObjectiveManager mgr = RndObjectiveManager.Instance;
				if (contract == null || (Object)(object)mgr == (Object)null)
				{
					return;
				}
				SubGenerationSettings subGenerationSettings = __instance.subGenerationSettings;
				MazePipeline.Config config = new MazePipeline.Config
				{
					MazeType = (int)contract.MazeType,
					SubmazeTries = __instance.submazeTries,
					StructureAttempts = __instance.structureAttempts,
					EdgeDist = __instance.landmarkDistanceFromEdge,
					MinRequired = __instance.minRequiredLandmarksSpawned,
					MinDistStartEnd = __instance.minDistanceFromStartToEndPiece,
					MinDistEdge = __instance.minDistanceFromEdgeToStartEndPiece,
					CanChangeDist = __instance.canChangeLandmarkDistance,
					RequireAtLeastOneLandmark = __instance.requireAtLeastOneLandmark,
					SubChance = ((subGenerationSettings != null) ? subGenerationSettings.chance : 0f),
					SubRMin = ((subGenerationSettings != null) ? subGenerationSettings.radiusMin : 0),
					SubRMax = ((subGenerationSettings != null) ? subGenerationSettings.radiusMax : 0),
					SubPct = ((subGenerationSettings != null) ? subGenerationSettings.radiusMaxMapPercent : 0f),
					Subs = ((IEnumerable<Submaze>)__instance.possibleSubmazes)?.Select((Submaze x) => (x != null) ? new MazePipeline.Submaze
					{
						RadiusMin = x.submazeRadiusMin,
						RadiusMax = x.submazeRadiusMax,
						SpawnTries = x.spawnTries,
						Chance = x.chanceToSpawn,
						CanPlaceSafezones = x.canPlaceSafezones
					} : null).ToArray(),
					SafeCells = __instance.safezoneCells,
					SafeMinSpawned = __instance.minSafezonesSpawned,
					SafeMinTried = __instance.minSafezonesTriedToSpawn,
					SafeDistStart = __instance.safezoneMinDistanceToStart,
					SafeDistLandmark = __instance.safezoneMinDistanceToLandmark,
					SafeDistOthers = __instance.safezoneMinDistanceToOthers,
					GridSize = __instance.SafezoneGrid.Size,
					GridSpacing = __instance.SafezoneGrid.Spacing,
					MoveSafezonesForward = __instance.moveSafezonesForward,
					Required = ((IEnumerable<MazeStructure>)__instance.requiredLandmarks)?.Select(MazeStructuresTest.ToStructure).ToArray(),
					Puzzles = ((IEnumerable<MazeStructure>)__instance.puzzleStructures)?.Select(MazeStructuresTest.ToStructure).ToArray(),
					Landmarks = ((IEnumerable<MazeStructure>)__instance.landmarkStructures)?.Select(MazeStructuresTest.ToStructure).ToArray(),
					Sets = ((IEnumerable<ObjectiveSet>)mgr.objectiveSets)?.Select((ObjectiveSet s) => (s != null) ? new MazePipeline.ObjectiveSet
					{
						MinMapSize = (int)s.minRequiredMapSize,
						Objectives = ((from o in ((IEnumerable<CaseObjectiveConfig>)s.objectives)?.Where((CaseObjectiveConfig o) => (Object)(object)((o != null) ? o.objective : null) != (Object)null)
							select ((Object)o.objective).name).ToArray() ?? new string[0])
					} : null).ToArray(),
					Tile = MazeGenerator.TILE_SIZE,
					MaxWaypointsDistance = MazeWaypointsTest.MaxWaypointsDistance(),
					Waypoints = ((IEnumerable<AIWaypointsGenerator>)__instance.aiWaypointsGenerators)?.Select((AIWaypointsGenerator x) => (!((Object)(object)x == (Object)null)) ? MazeWaypointsTest.ToGenerator(x) : null).ToArray()
				};
				if (mgr.objectiveSets != null)
				{
					foreach (ObjectiveSet item in (Il2CppArrayBase<ObjectiveSet>)(object)mgr.objectiveSets)
					{
						foreach (CaseObjectiveConfig item2 in (Il2CppArrayBase<CaseObjectiveConfig>)(object)(((item != null) ? item.objectives : null) ?? new Il2CppReferenceArray<CaseObjectiveConfig>(0L)))
						{
							object obj;
							if (item2 == null)
							{
								obj = null;
							}
							else
							{
								CaseObjectiveSO objective = item2.objective;
								obj = ((objective != null) ? ((Il2CppObjectBase)objective).TryCast<CaseObjectiveWithLandmarkSO>() : null);
							}
							CaseObjectiveWithLandmarkSO val = (CaseObjectiveWithLandmarkSO)obj;
							if (!((Object)(object)val == (Object)null) && !config.LandmarkObjectives.ContainsKey(((Object)val).name))
							{
								config.LandmarkObjectives[((Object)val).name] = new MazePipeline.LandmarkObjective
								{
									Min = val.MinLandmarksToSpawn,
									Landmarks = (((IEnumerable<MazeStructure>)val.GetRequiredLandmarks(contract.MazeType))?.ToArray().Select(MazeStructuresTest.ToStructure).ToArray() ?? new MazeStructures.Structure[0])
								};
							}
						}
					}
				}
				MazePipeline.Store(config);
				ContractPredictor.ClearOutcomes();
				if (ConfigManager.Instance.DebugMazeTests.Value)
				{
					ScenePreload.Check(config.MazeType, config, null);
					int num = MazePipeline.SelectObjectiveSet(config, ContractPredictor.ToInput(contract));
					int num2 = ((mgr.objectiveSets == null) ? (-1) : Array.FindIndex(((IEnumerable<ObjectiveSet>)mgr.objectiveSets).ToArray(), (ObjectiveSet s) => s != null && mgr.activeObjectiveSet != null && ((Il2CppObjectBase)s).Pointer == ((Il2CppObjectBase)mgr.activeObjectiveSet).Pointer));
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(93, 6);
					defaultInterpolatedStringHandler.AppendLiteral("\ud83e\uddeaObjectiveSet ");
					defaultInterpolatedStringHandler.AppendFormatted((num == num2) ? "MATCH" : "MISMATCH");
					defaultInterpolatedStringHandler.AppendLiteral(" predicted=");
					defaultInterpolatedStringHandler.AppendFormatted(num);
					defaultInterpolatedStringHandler.AppendLiteral(" actual=");
					defaultInterpolatedStringHandler.AppendFormatted(num2);
					defaultInterpolatedStringHandler.AppendLiteral(" | captured tile=");
					defaultInterpolatedStringHandler.AppendFormatted(config.Tile);
					defaultInterpolatedStringHandler.AppendLiteral(" maxWaypointsDistance=");
					defaultInterpolatedStringHandler.AppendFormatted(config.MaxWaypointsDistance, "R");
					defaultInterpolatedStringHandler.AppendLiteral(" waypointGenerators=");
					MazeWaypoints.Generator[] waypoints = config.Waypoints;
					defaultInterpolatedStringHandler.AppendFormatted((waypoints != null) ? waypoints.Length : 0);
					MelonLogger.Msg(defaultInterpolatedStringHandler.ToStringAndClear());
				}
			}
			catch (Exception value)
			{
				MelonLogger.Warning($"Maze capture failed: {value}");
			}
		}
	}
	public static class MazeChecks
	{
		public sealed class Safezones
		{
			public int Cells;

			public int MinSpawned;

			public int MinTried;

			public int DistStart;

			public int DistLandmark;

			public int DistOthers;

			public bool MoveForward;

			public int GridSize;

			public int GridSpacing;

			public float ReduceMapSize = -1f;

			public bool[] SubCanPlace;
		}

		public sealed class World
		{
			public MazeSubmazes.State S;

			public List<MazeStructures.Placed> Spawned = new List<MazeStructures.Placed>();

			public List<MazeStructures.Placed> Puzzles = new List<MazeStructures.Placed>();
		}

		private sealed class SlotSet
		{
			private readonly List<(int x, int y)?> slots = new List<(int, int)?>();

			private readonly Stack<int> free = new Stack<int>();

			private readonly Dictionary<(int, int), int> index = new Dictionary<(int, int), int>();

			public int Count => index.Count;

			public bool Contains((int, int) p)
			{
				return index.ContainsKey(p);
			}

			public void Add((int x, int y) p)
			{
				if (!index.ContainsKey(p))
				{
					int value;
					if (free.Count > 0)
					{
						value = free.Pop();
						slots[value] = p;
					}
					else
					{
						value = slots.Count;
						slots.Add(p);
					}
					index[p] = value;
				}
			}

			public void Remove((int, int) p)
			{
				if (index.Remove(p, out var value))
				{
					slots[value] = null;
					free.Push(value);
				}
			}

			public IEnumerable<(int x, int y)> Items()
			{
				foreach ((int, int)? slot in slots)
				{
					if (slot.HasValue)
					{
						yield return slot.Value;
					}
				}
			}
		}

		private const int Walkable = 0;

		private const int Wall = 1;

		private const int Landmark = 2;

		private const int Safezone = 3;

		private const int LandmarkBorder = 4;

		public static void RemoveInvalidTransitions(World w)
		{
			MazeSubmazes.State s = w.S;
			if (s.Transitions == null || s.Transitions.Count == 0)
			{
				return;
			}
			foreach (var item in s.Transitions.Keys.Where(((int x, int y) k) => !IsStraight(s, k.x, k.y, dirY: true) && !IsStraight(s, k.x, k.y, dirY: false)).ToList())
			{
				s.Transitions.Remove(item);
				SetTile(s, item.x, item.y, 1);
			}
		}

		public static void FillCustomUnwalkable(World w)
		{
			w.S.CustomUnwalkable.Clear();
			foreach (MazeStructures.Placed item in w.Spawned)
			{
				if (item.S.NonWalkable != null)
				{
					(int, int)[] nonWalkable = item.S.NonWalkable;
					for (int i = 0; i < nonWalkable.Length; i++)
					{
						(int, int) tuple = nonWalkable[i];
						w.S.CustomUnwalkable.Add((item.X + tuple.Item1, item.Y + tuple.Item2));
					}
				}
			}
		}

		private static bool InMaze(MazeSubmazes.State s, int x, int y)
		{
			if (x >= 0 && y >= 0 && x < s.MazeX)
			{
				return y < s.MazeY;
			}
			return false;
		}

		private static bool InMap(MazeSubmazes.State s, int x, int y)
		{
			if ((uint)x < (uint)s.Map.GetLength(0))
			{
				return (uint)y < (uint)s.Map.GetLength(1);
			}
			return false;
		}

		private static void SetTile(MazeSubmazes.State s, int x, int y, int v)
		{
			if (InMap(s, x, y))
			{
				s.Map[x, y] = v;
			}
		}

		private static bool IsStraight(MazeSubmazes.State s, int x, int y, bool dirY)
		{
			if (!Open(x, y))
			{
				return false;
			}
			bool flag = Open(x, y + 1);
			bool flag2 = Open(x, y - 1);
			bool flag3 = Open(x + 1, y);
			bool flag4 = Open(x - 1, y);
			if (!dirY)
			{
				return !flag && !flag2 && flag4 && flag3;
			}
			if (flag && flag2 && !flag3)
			{
				return !flag4;
			}
			return false;
			bool Open(int a, int b)
			{
				if (InMaze(s, a, b))
				{
					return s.Map[a, b] != 1;
				}
				return false;
			}
		}

		private static bool InPf(MazeSubmazes.State s, int x, int y)
		{
			if (x >= 0 && y >= 0 && x < s.PfRows)
			{
				return y < s.PfCols;
			}
			return false;
		}

		private static bool CollidesWithStartOrEnd(MazeSubmazes.State s, int x, int y)
		{
			(int, int)[] array = new(int, int)[4]
			{
				(x - 1, y),
				(x, y - 1),
				(x, y + 1),
				(x + 1, y)
			};
			for (int i = 0; i < array.Length; i++)
			{
				var (num, num2) = array[i];
				if (!InPf(s, num, num2))
				{
					continue;
				}
				int num3 = s.Map[num, num2];
				if (num3 == 100)
				{
					int num4 = s.Start.x - x;
					int num5 = s.Start.y - y;
					(int, int) startDir = s.StartDir;
					if (num4 != startDir.Item1 || num5 != startDir.Item2)
					{
						return true;
					}
				}
				if (num3 == 101)
				{
					int num6 = s.End.x - x;
					int num5 = s.End.y - y;
					(int, int) startDir = s.EndDir;
					if (num6 != startDir.Item1 || num5 != startDir.Item2)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryTransition(MazeSubmazes.State s, int x, int y, out MazeSubmazes.Trans t)
		{
			t = default(MazeSubmazes.Trans);
			if (s.Transitions != null)
			{
				return s.Transitions.TryGetValue((x, y), out t);
			}
			return false;
		}

		private static bool SameSubmazeAround(MazeSubmazes.State s, int x, int y, int r)
		{
			for (int i = x - r; i <= x + r; i++)
			{
				for (int j = y - r; j <= y + r; j++)
				{
					if (InMaze(s, i, j) && s.Types[i, j] != s.Types[x, y])
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool NodeOk(MazeSubmazes.State s, int x, int y, int curX, bool ignoreWalls, bool useTypes)
		{
			if (!InPf(s, x, y) || CollidesWithStartOrEnd(s, x, y))
			{
				return false;
			}
			if (s.CustomUnwalkable.Contains((x, y)))
			{
				return false;
			}
			if (!ignoreWalls)
			{
				return s.Map[x, y] != 1;
			}
			for (int i = x - 1; i <= x + 1; i++)
			{
				for (int j = y - 1; j <= y + 1; j++)
				{
					if (InPf(s, i, j) && s.Map[i, j] == 2)
					{
						return false;
					}
				}
			}
			if (!useTypes)
			{
				return true;
			}
			for (int k = -1; k <= 1; k++)
			{
				for (int l = -1; l <= 1; l++)
				{
					if ((Math.Abs(k) != 1 || Math.Abs(l) != 1) && TryTransition(s, x + k, y + l, out var t) && t.Vertical != (k == 0))
					{
						return false;
					}
				}
			}
			if (!SameSubmazeAround(s, x, y, 1) && (!TryTransition(s, x, y, out var t2) || x == curX != t2.Vertical))
			{
				return false;
			}
			return true;
		}

		private static (int x, int y) ProcessPosition(MazeSubmazes.State s, (int x, int y) p)
		{
			(int, int) tuple = p;
			(int, int) start = s.Start;
			if (tuple.Item1 == start.Item1 && tuple.Item2 == start.Item2)
			{
				p = (x: p.x - s.StartDir.x, y: p.y - s.StartDir.y);
			}
			else
			{
				start = p;
				tuple = s.End;
				if (start.Item1 == tuple.Item1 && start.Item2 == tuple.Item2)
				{
					p = (x: p.x - s.EndDir.x, y: p.y - s.EndDir.y);
				}
			}
			return (x: (p.x >= 0) ? Math.Min(p.x, s.PfRows - 1) : 0, y: (p.y >= 0) ? Math.Min(p.y, s.PfCols - 1) : 0);
		}

		private static int Manhattan((int x, int y) a, (int x, int y) b)
		{
			return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
		}

		public static bool FindPath(MazeSubmazes.State s, (int x, int y) from, (int x, int y) to, List<(int x, int y)> path, bool ignoreWalls, bool useTypes)
		{
			from = ProcessPosition(s, from);
			to = ProcessPosition(s, to);
			Dictionary<(int, int), int> g = new Dictionary<(int, int), int>();
			Dictionary<(int, int), int> dictionary = new Dictionary<(int, int), int>();
			Dictionary<(int, int), (int, int)> dictionary2 = new Dictionary<(int, int), (int, int)>();
			SlotSet slotSet = new SlotSet();
			SlotSet slotSet2 = new SlotSet();
			slotSet.Add(from);
			g[from] = 0;
			dictionary[from] = Manhattan(from, to);
			while (slotSet.Count > 0)
			{
				(int, int) tuple = default((int, int));
				bool flag = true;
				foreach (var item in slotSet.Items())
				{
					if (flag || dictionary[item] < dictionary[tuple])
					{
						tuple = item;
						flag = false;
					}
				}
				(int, int) tuple2 = tuple;
				(int, int) tuple3 = to;
				if (tuple2.Item1 == tuple3.Item1 && tuple2.Item2 == tuple3.Item2)
				{
					if (path != null)
					{
						path.Clear();
						(int, int) tuple4 = tuple;
						while (true)
						{
							path.Add(tuple4);
							if (!dictionary2.ContainsKey(tuple4))
							{
								break;
							}
							tuple4 = dictionary2[tuple4];
						}
					}
					return true;
				}
				slotSet.Remove(tuple);
				slotSet2.Add(tuple);
				(int, int)[] array = new(int, int)[4]
				{
					(tuple.Item1, tuple.Item2 + 1),
					(tuple.Item1, tuple.Item2 - 1),
					(tuple.Item1 + 1, tuple.Item2),
					(tuple.Item1 - 1, tuple.Item2)
				};
				for (int i = 0; i < array.Length; i++)
				{
					(int, int) tuple5 = array[i];
					if (!NodeOk(s, tuple5.Item1, tuple5.Item2, tuple.Item1, ignoreWalls, useTypes) || slotSet2.Contains(tuple5))
					{
						continue;
					}
					int num = G(tuple) + 1;
					if (num < G(tuple5))
					{
						dictionary2[tuple5] = tuple;
						g[tuple5] = num;
						dictionary[tuple5] = num + Manhattan(tuple5, to);
						if (!slotSet.Contains(tuple5))
						{
							slotSet.Add(tuple5);
						}
					}
				}
			}
			if (path != null)
			{
				path.Clear();
				path.AddRange(slotSet2.Items());
			}
			return false;
			int G((int, int) p)
			{
				if (!g.TryGetValue(p, out var value))
				{
					return int.MaxValue;
				}
				return value;
			}
		}

		private static float Dist((int x, int y) a, (int x, int y) b)
		{
			float num = (float)a.x - (float)b.x;
			float num2 = (float)a.y - (float)b.y;
			return (float)Math.Sqrt(num2 * num2 + num * num);
		}

		public static bool EnsureExitIsReachable(World w, bool useTypes)
		{
			MazeSubmazes.State s = w.S;
			List<(int, int)> list = new List<(int, int)>();
			if (FindPath(s, s.Start, s.End, list, ignoreWalls: false, useTypes: false))
			{
				return true;
			}
			List<(int, int)> list2 = list.OrderBy<(int, int), float>(((int x, int y) p) => Dist(p, s.End)).ToList();
			int num = Math.Min(list2.Count, 10);
			for (int num2 = 0; num2 < num; num2++)
			{
				if (!FindPath(s, list2[num2], s.End, list, ignoreWalls: true, useTypes))
				{
					continue;
				}
				foreach (var item in list)
				{
					SetTile(s, item.Item1, item.Item2, 0);
				}
				return true;
			}
			return false;
		}

		public static void RemoveUnreachableAreas(World w)
		{
			MazeSubmazes.State s = w.S;
			(int, int) to = s.Start;
			for (int i = 0; i < s.PfRows; i++)
			{
				for (int j = 0; j < s.PfCols; j++)
				{
					int num = s.Map[i, j];
					if (num == 0 || num == 2 || num == 4)
					{
						if (MazeSubmazes.CanReachPoint(s, (x: i, y: j), to))
						{
							to = (i, j);
						}
						else
						{
							s.Map[i, j] = 1;
						}
					}
				}
			}
		}

		public static bool RemoveUnreachableLandmarks(World w)
		{
			MazeSubmazes.State s = w.S;
			if (w.Spawned.Count == 0)
			{
				return false;
			}
			List<MazeStructures.Placed> list = new List<MazeStructures.Placed>();
			List<MazeStructures.Placed> list2 = new List<MazeStructures.Placed>();
			bool result = false;
			FillCustomUnwalkable(w);
			foreach (MazeStructures.Placed item in w.Spawned)
			{
				if (!IsLandmarkValid(s, item) || !CanReachLandmark(s, item))
				{
					result = true;
					for (int i = 0; i < item.S.DimX; i++)
					{
						for (int j = 0; j < item.S.DimY; j++)
						{
							SetTile(s, item.X + i, item.Y + j, 1);
						}
					}
				}
				else
				{
					list.Add(item);
					if (w.Puzzles.Contains(item))
					{
						list2.Add(item);
					}
				}
			}
			w.Spawned = list;
			w.Puzzles = list2;
			return result;
		}

		private static bool IsLandmarkValid(MazeSubmazes.State s, MazeStructures.Placed p)
		{
			for (int i = 0; i < p.S.DimX; i++)
			{
				for (int j = 0; j < p.S.DimY; j++)
				{
					if (p.S.BorderTile(i, j) != 1)
					{
						int num = s.Map[p.X + i, p.Y + j];
						if (num != 2 && num != 4)
						{
							return false;
						}
					}
				}
			}
			return true;
		}

		private static bool CanReachLandmark(MazeSubmazes.State s, MazeStructures.Placed p)
		{
			for (int i = 0; i < p.S.DimX; i++)
			{
				for (int j = 0; j < p.S.DimY; j++)
				{
					if (s.Map[p.X + i, p.Y + j] == 2)
					{
						return MazeSubmazes.CanReachStartOrEnd(s, (x: p.X + i, y: p.Y + j));
					}
				}
			}
			return false;
		}

		public static bool RequiredLandmarksExist(World w, MazeStructures.Structure[] required, int minRequired)
		{
			int num = 0;
			if (required != null)
			{
				foreach (MazeStructures.Structure r in required)
				{
					if (r != null && w.Spawned.Any((MazeStructures.Placed p) => p.S.PrefabId == r.PrefabId))
					{
						num++;
					}
				}
			}
			retu