Decompiled source of TellMeCosmetics v1.0.3
TellMeCosmetics.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
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