Decompiled source of TellMeCosmetics v0.1.4

TellMeCosmetics.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using Il2CppCharacterCustomization;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using TellMeCosmetics;
using TellMeCosmetics.Config;
using TellMeCosmetics.UI;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: VerifyLoaderVersion(0, 6, 6, true)]
[assembly: MelonInfo(typeof(CustomizationPickupFinderMod), "Tell Me Cosmetics", "0.1.4", "0.1.4", null)]
[assembly: MelonGame("Valko Game Studios", "Labyrinthine")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("TellMeCosmetics")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.4.0")]
[assembly: AssemblyInformationalVersion("0.1.4")]
[assembly: AssemblyProduct("Tell Me Cosmetics")]
[assembly: AssemblyTitle("TellMeCosmetics")]
[assembly: AssemblyVersion("0.1.4.0")]
internal static class ModInfo
{
	public const string Name = "Tell Me Cosmetics";

	public const string Version = "0.1.4";

	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(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 GameplayConfig config;

		internal static CustomizationPickupFinderMod Instance { get; private set; }

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

		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 && sceneName == "MainMenu" && (alertui == null || alertui.IsDestroy()))
			{
				MelonCoroutines.Start(InitUI());
			}
		}

		private IEnumerator InitItemsCollectionSO()
		{
			if ((Object)(object)itemsCollection == (Object)null)
			{
				yield return null;
				ItemsCollectionSO[] ic = Il2CppArrayBase<ItemsCollectionSO>.op_Implicit(Resources.FindObjectsOfTypeAll<ItemsCollectionSO>());
				if (ic.Length != 0)
				{
					itemsCollection = ic[0];
					((MelonBase)this).LoggerInstance.Msg("Init itemsCollectionSO Class");
				}
			}
		}

		private IEnumerator InitUI()
		{
			yield return (object)new WaitForSeconds(1f);
			try
			{
				GameObject tabMenu = GameObject.Find("Global/Global Canvas/Player_UI/Tab Menu");
				if ((Object)(object)tabMenu == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("UI Tab Menu not found!");
					yield break;
				}
				RectTransform ui = tabMenu.GetComponent<RectTransform>();
				if ((Object)(object)ui == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("UI RectTransform missing!");
					yield break;
				}
				itemsCollection = ((IEnumerable<ItemsCollectionSO>)Resources.FindObjectsOfTypeAll<ItemsCollectionSO>()).FirstOrDefault();
				if ((Object)(object)itemsCollection == (Object)null)
				{
					((MelonBase)this).LoggerInstance.Warning("ItemsCollectionSO not found!");
					yield break;
				}
				((MelonBase)this).LoggerInstance.Msg("Initializing UI components...");
				alertui = new ItemAlertUI(ui, itemsCollection);
				((MelonBase)this).LoggerInstance.Msg("UI initialized successfully.");
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error($"[InitUI] Exception: {ex}");
			}
		}

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

		internal void Show(CustomizationPickup item)
		{
			((MelonBase)this).LoggerInstance.Msg($"\ud83d\udce6Spawned Cosmetic ItemID {item.ItemID} {((Object)item).name}!");
			if (!config.RevealAll.Value && SaveInstance != null)
			{
				alertui?.Show(item, SaveInstance.IsItemUnlocked(item.ItemID));
			}
			else
			{
				alertui?.Show(item);
			}
		}

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

		internal void UpdateSave(CustomizationSave save)
		{
			if (save != null)
			{
				SaveInstance = save;
			}
		}
	}
}
namespace TellMeCosmetics.UI
{
	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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: 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 val = ui_object.AddComponent<RectTransform>();
			val.anchorMin = new Vector2(0f, 0f);
			val.anchorMax = new Vector2(0f, 0f);
			val.pivot = new Vector2(0f, 0f);
			val.anchoredPosition = new Vector2(0f, 0f);
			val.sizeDelta = new Vector2(0f, 50f);
			HorizontalLayoutGroup val2 = ui_object.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)val2).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)val2).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;
			RectTransform component = iconObject.GetComponent<RectTransform>();
			component.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;
			RectTransform component2 = iconAltObject.GetComponent<RectTransform>();
			component2.sizeDelta = new Vector2(64f, 64f);
			GameObject val3 = new GameObject("Item Name");
			val3.transform.SetParent(ui_object.transform, false);
			myText = val3.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 = '?')
		{
			((TMP_Text)myText).text = itemText;
			((TMP_Text)myText).fontStyle = (FontStyles)0;
			iconImage.sprite = icon;
			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_0138: 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_0164: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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 (!reveal)
			{
				SetItemUI("Undiscovered Item");
			}
			else if (itemsCollection != null && itemsCollection.Length >= 0)
			{
				if (itemID >= itemsCollection.Length)
				{
					throw new Exception("Out of itemID index to search");
				}
				CustomizationItem val = itemsCollection[itemID];
				string itemText = $"#{itemID} " + ((!string.IsNullOrEmpty(val.Name)) ? val.Name : ((Object)val.icon).name).Replace("_", " ") + " " + $"({val.ItemRarity})";
				BodyPart bodyPart = val.BodyPart;
				BodyPart val2 = bodyPart;
				if ((int)val2 == 100)
				{
					SetItemUI(itemText, null, '♫');
				}
				else
				{
					SetItemUI(itemText, val.Icon);
				}
			}
			else
			{
				SetItemUI($"#{itemID} {FilterClone(((Object)item).name)}");
			}
		}

		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.Config
{
	public static class ConfigManager
	{
		private static readonly string configPath = Path.Combine(MelonEnvironment.UserDataDirectory, "TellMeCosmetics.cfg");

		public static GameplayConfig Load()
		{
			MelonPreferences_Category val = MelonPreferences.CreateCategory("Gameplay");
			val.SetFilePath(configPath);
			return new GameplayConfig(val);
		}
	}
	public class GameplayConfig
	{
		public MelonPreferences_Entry<bool> RevealAll { get; set; }

		public GameplayConfig(MelonPreferences_Category category)
		{
			RevealAll = category.CreateEntry<bool>("RevealAllItems", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		}
	}
}