Decompiled source of CosmeticTryOn v4.0.0

CosmeticTryOn.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.CosmeticTryOn
{
	[BepInPlugin("REPOJP.CosmeticTryOn", "CosmeticTryOn", "4.0.0")]
	public sealed class CosmeticTryOnPlugin : BaseUnityPlugin
	{
		private static class TextMeshProUGUIBridge
		{
			public static void SetText(object textObject, string value)
			{
				if (textObject != null)
				{
					PropertyInfo property = textObject.GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public);
					if (property != null && property.CanWrite)
					{
						property.SetValue(textObject, value, null);
					}
				}
			}
		}

		public const string PluginGuid = "REPOJP.CosmeticTryOn";

		public const string PluginName = "CosmeticTryOn";

		public const string PluginVersion = "4.0.0";

		private const string BuildMarker = "FixedClientTryOn-20260512";

		private static CosmeticTryOnPlugin instance;

		private static ManualLogSource log;

		private Harmony harmony;

		private const bool EnableDebugLog = false;

		private const string TryOnLabelText = "TRY-ON MODE\nClick locked cosmetics to wear temporarily\nPreview only / Not saved";

		private const float LockedIconOpacity = 0.85f;

		private static Type typeMetaManager;

		private static Type typeCosmeticAsset;

		private static Type typeMenuElementCosmeticButton;

		private static Type typeMenuPageCosmetics;

		private static Type typeRunManager;

		private static Type typeLevelGenerator;

		private static FieldInfo fieldMetaInstance;

		private static FieldInfo fieldMetaCosmeticUnlocks;

		private static FieldInfo fieldMetaCosmeticEquipped;

		private static FieldInfo fieldMetaCosmeticEquippedPreview;

		private static FieldInfo fieldMetaColorsEquipped;

		private static FieldInfo fieldMetaColorsEquippedPreview;

		private static FieldInfo fieldMetaCosmeticPresets;

		private static FieldInfo fieldMetaCosmeticAssets;

		private static FieldInfo fieldMetaColors;

		private static MethodInfo methodMetaCosmeticPreviewSet;

		private static MethodInfo methodMetaCosmeticPlayerUpdateLocal;

		private static MethodInfo methodMetaGetCosmeticsToUnequip;

		private static MethodInfo methodMetaCosmeticUnequip;

		private static FieldInfo fieldButtonCosmeticAsset;

		private static FieldInfo fieldButtonCosmeticIndex;

		private static FieldInfo fieldButtonMenuButton;

		private static FieldInfo fieldButtonIconImage;

		private static FieldInfo fieldButtonIconText;

		private static FieldInfo fieldButtonBgBorder;

		private static FieldInfo fieldButtonTintableButton;

		private static MethodInfo methodButtonUpdateIcon;

		private static FieldInfo fieldMenuButtonDisabled;

		private static FieldInfo fieldCosmeticType;

		private static FieldInfo fieldCosmeticDefaultColor;

		private static MethodInfo methodCosmeticGetIcon;

		private static MethodInfo methodCosmeticGetRarityColor;

		private static bool tryOnActive;

		private static bool tryOnPinned;

		private static bool hoverPreviewActive;

		private static bool rebuildingTryOnPreview;

		private static bool forceClearingPreview;

		private static int currentLockedIndex = -1;

		private static object currentLockedAsset;

		private static readonly List<int> pinnedTryOnOrder = new List<int>();

		private static readonly Dictionary<int, object> pinnedTryOnAssets = new Dictionary<int, object>();

		private void Awake()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			try
			{
				instance = this;
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				log = ((BaseUnityPlugin)this).Logger;
				InitializeReflection();
				harmony = new Harmony("REPOJP.CosmeticTryOn");
				ApplyPatches();
				WriteDebug("Plugin loaded");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Awake\n" + ex));
			}
		}

		private void OnDestroy()
		{
			try
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failure: OnDestroy\n" + ex));
			}
		}

		private void OnGUI()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (IsEnabled() && tryOnActive)
				{
					string text = "TRY-ON MODE\nClick locked cosmetics to wear temporarily\nPreview only / Not saved";
					GUIStyle val = new GUIStyle(GUI.skin.box);
					val.alignment = (TextAnchor)4;
					val.fontSize = 16;
					val.wordWrap = true;
					Rect val2 = default(Rect);
					((Rect)(ref val2))..ctor((float)Screen.width - 300f, 24f, 260f, 58f);
					GUI.Box(val2, text, val);
				}
			}
			catch (Exception ex)
			{
				WriteFailure("OnGUI", ex);
			}
		}

		private static void InitializeReflection()
		{
			typeMetaManager = AccessTools.TypeByName("MetaManager");
			typeCosmeticAsset = AccessTools.TypeByName("CosmeticAsset");
			typeMenuElementCosmeticButton = AccessTools.TypeByName("MenuElementCosmeticButton");
			typeMenuPageCosmetics = AccessTools.TypeByName("MenuPageCosmetics");
			typeRunManager = AccessTools.TypeByName("RunManager");
			typeLevelGenerator = AccessTools.TypeByName("LevelGenerator");
			if (typeMetaManager == null || typeCosmeticAsset == null || typeMenuElementCosmeticButton == null)
			{
				throw new InvalidOperationException("Required REPO cosmetic types were not found");
			}
			fieldMetaInstance = AccessTools.Field(typeMetaManager, "instance");
			fieldMetaCosmeticUnlocks = AccessTools.Field(typeMetaManager, "cosmeticUnlocks");
			fieldMetaCosmeticEquipped = AccessTools.Field(typeMetaManager, "cosmeticEquipped");
			fieldMetaCosmeticEquippedPreview = AccessTools.Field(typeMetaManager, "cosmeticEquippedPreview");
			fieldMetaColorsEquipped = AccessTools.Field(typeMetaManager, "colorsEquipped");
			fieldMetaColorsEquippedPreview = AccessTools.Field(typeMetaManager, "colorsEquippedPreview");
			fieldMetaCosmeticPresets = AccessTools.Field(typeMetaManager, "cosmeticPresets");
			fieldMetaCosmeticAssets = AccessTools.Field(typeMetaManager, "cosmeticAssets");
			fieldMetaColors = AccessTools.Field(typeMetaManager, "colors");
			methodMetaCosmeticPreviewSet = AccessTools.Method(typeMetaManager, "CosmeticPreviewSet", new Type[1] { typeof(bool) }, (Type[])null);
			methodMetaCosmeticPlayerUpdateLocal = AccessTools.Method(typeMetaManager, "CosmeticPlayerUpdateLocal", new Type[2]
			{
				typeof(bool),
				typeof(bool)
			}, (Type[])null);
			methodMetaGetCosmeticsToUnequip = AccessTools.Method(typeMetaManager, "GetCosmeticsToUnequip", (Type[])null, (Type[])null);
			methodMetaCosmeticUnequip = AccessTools.Method(typeMetaManager, "CosmeticUnequip", (Type[])null, (Type[])null);
			fieldButtonCosmeticAsset = AccessTools.Field(typeMenuElementCosmeticButton, "cosmeticAsset");
			fieldButtonCosmeticIndex = AccessTools.Field(typeMenuElementCosmeticButton, "cosmeticIndex");
			fieldButtonMenuButton = AccessTools.Field(typeMenuElementCosmeticButton, "menuButton");
			fieldButtonIconImage = AccessTools.Field(typeMenuElementCosmeticButton, "iconImage");
			fieldButtonIconText = AccessTools.Field(typeMenuElementCosmeticButton, "iconText");
			fieldButtonBgBorder = AccessTools.Field(typeMenuElementCosmeticButton, "bgBorder");
			fieldButtonTintableButton = AccessTools.Field(typeMenuElementCosmeticButton, "tintableButton");
			methodButtonUpdateIcon = AccessTools.Method(typeMenuElementCosmeticButton, "UpdateIcon", (Type[])null, (Type[])null);
			Type type = AccessTools.TypeByName("MenuButton");
			if (type != null)
			{
				fieldMenuButtonDisabled = AccessTools.Field(type, "disabled");
			}
			fieldCosmeticType = AccessTools.Field(typeCosmeticAsset, "type");
			fieldCosmeticDefaultColor = AccessTools.Field(typeCosmeticAsset, "defaultColor");
			methodCosmeticGetIcon = AccessTools.Method(typeCosmeticAsset, "GetIcon", (Type[])null, (Type[])null);
			methodCosmeticGetRarityColor = AccessTools.Method(typeCosmeticAsset, "GetRarityColor", (Type[])null, (Type[])null);
		}

		private void ApplyPatches()
		{
			PatchMethod(typeMetaManager, "CosmeticEquip", "MetaManager_CosmeticEquip_Prefix", prefix: true, postfix: false);
			PatchMethod(typeMetaManager, "CosmeticPreviewSet", "MetaManager_CosmeticPreviewSet_Prefix", prefix: true, postfix: false);
			PatchMethod(typeMetaManager, "Save", "MetaManager_Save_Prefix", prefix: true, postfix: false);
			PatchMethod(typeMenuElementCosmeticButton, "Start", "MenuElementCosmeticButton_Start_Postfix", prefix: false, postfix: true);
			PatchMethod(typeMenuElementCosmeticButton, "UpdateIcon", "MenuElementCosmeticButton_UpdateIcon_Postfix", prefix: false, postfix: true);
			PatchMethod(typeMenuElementCosmeticButton, "ToggleCosmetic", "MenuElementCosmeticButton_ToggleCosmetic_Prefix", prefix: true, postfix: false);
			if (typeMenuPageCosmetics != null)
			{
				PatchMethod(typeMenuPageCosmetics, "ConfirmButton", "MenuPageCosmetics_ConfirmButton_Prefix", prefix: true, postfix: false);
				PatchMethod(typeMenuPageCosmetics, "OnDestroy", "MenuPageCosmetics_OnDestroy_Postfix", prefix: false, postfix: true);
			}
			if (typeRunManager != null)
			{
				PatchMethod(typeRunManager, "ChangeLevel", "RunManager_ChangeLevel_Prefix", prefix: true, postfix: false);
			}
			if (typeLevelGenerator != null)
			{
				PatchMethod(typeLevelGenerator, "GenerateDone", "LevelGenerator_GenerateDone_Postfix", prefix: false, postfix: true);
			}
		}

		private void PatchMethod(Type targetType, string targetName, string patchName, bool prefix, bool postfix)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			if (targetType == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(targetType, targetName, (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(CosmeticTryOnPlugin), patchName, (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				WriteDebug("Patch skipped: " + targetType.Name + "." + targetName);
				return;
			}
			HarmonyMethod val = new HarmonyMethod(methodInfo2);
			if (prefix)
			{
				harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			if (postfix)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static bool IsEnabled()
		{
			return true;
		}

		private static void WriteDebug(string message)
		{
			_ = log;
		}

		private static void WriteFailure(string message, Exception ex)
		{
			if (log != null)
			{
				log.LogError((object)("Failure: " + message + "\n" + ex));
			}
		}

		private static object GetMetaManager()
		{
			if (fieldMetaInstance == null)
			{
				return null;
			}
			return fieldMetaInstance.GetValue(null);
		}

		private static IList GetList(FieldInfo field, object instanceObject)
		{
			if (field == null || instanceObject == null)
			{
				return null;
			}
			return field.GetValue(instanceObject) as IList;
		}

		private static List<int> ToIntList(IList source)
		{
			List<int> list = new List<int>();
			if (source == null)
			{
				return list;
			}
			foreach (object item in source)
			{
				if (item is int)
				{
					list.Add((int)item);
				}
			}
			return list;
		}

		private static bool ListContainsInt(IList list, int value)
		{
			if (list == null)
			{
				return false;
			}
			foreach (object item in list)
			{
				if (item is int && (int)item == value)
				{
					return true;
				}
			}
			return false;
		}

		private static void ListAddInt(IList list, int value)
		{
			if (list != null && !ListContainsInt(list, value))
			{
				list.Add(value);
			}
		}

		private static void ListRemoveInt(IList list, int value)
		{
			if (list == null)
			{
				return;
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				object obj = list[num];
				if (obj is int && (int)obj == value)
				{
					list.RemoveAt(num);
				}
			}
		}

		private static int GetCosmeticIndex(object cosmeticAsset)
		{
			object metaManager = GetMetaManager();
			IList list = GetList(fieldMetaCosmeticAssets, metaManager);
			if (list == null || cosmeticAsset == null)
			{
				return -1;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] == cosmeticAsset)
				{
					return i;
				}
			}
			return -1;
		}

		private static object GetCosmeticAssetByIndex(int index)
		{
			object metaManager = GetMetaManager();
			IList list = GetList(fieldMetaCosmeticAssets, metaManager);
			if (list == null || index < 0 || index >= list.Count)
			{
				return null;
			}
			return list[index];
		}

		private static bool IsUnlocked(int cosmeticIndex)
		{
			object metaManager = GetMetaManager();
			IList list = GetList(fieldMetaCosmeticUnlocks, metaManager);
			return ListContainsInt(list, cosmeticIndex);
		}

		private static bool IsLockedCosmetic(object cosmeticAsset, int cosmeticIndex)
		{
			int num = cosmeticIndex;
			if (num < 0)
			{
				num = GetCosmeticIndex(cosmeticAsset);
			}
			if (num >= 0)
			{
				return !IsUnlocked(num);
			}
			return false;
		}

		private static int GetButtonCosmeticIndex(object button)
		{
			if (button == null || fieldButtonCosmeticIndex == null)
			{
				return -1;
			}
			object value = fieldButtonCosmeticIndex.GetValue(button);
			if (value is int)
			{
				return (int)value;
			}
			return -1;
		}

		private static object GetButtonCosmeticAsset(object button)
		{
			if (button == null || fieldButtonCosmeticAsset == null)
			{
				return null;
			}
			return fieldButtonCosmeticAsset.GetValue(button);
		}

		private static void SetButtonDisabled(object button, bool disabled)
		{
			if (button != null && !(fieldButtonMenuButton == null) && !(fieldMenuButtonDisabled == null))
			{
				object value = fieldButtonMenuButton.GetValue(button);
				if (value != null)
				{
					fieldMenuButtonDisabled.SetValue(value, disabled);
				}
			}
		}

		private static void InvokeButtonUpdateIcon(object button, bool initial)
		{
			try
			{
				if (button != null && methodButtonUpdateIcon != null)
				{
					methodButtonUpdateIcon.Invoke(button, new object[1] { initial });
				}
			}
			catch (Exception ex)
			{
				WriteFailure("InvokeButtonUpdateIcon", ex);
			}
		}

		private static void RefreshLocalCosmetics(bool forced)
		{
			try
			{
				object metaManager = GetMetaManager();
				if (metaManager != null && methodMetaCosmeticPlayerUpdateLocal != null)
				{
					methodMetaCosmeticPlayerUpdateLocal.Invoke(metaManager, new object[2] { false, forced });
				}
			}
			catch (Exception ex)
			{
				WriteFailure("RefreshLocalCosmetics", ex);
			}
		}

		private static void SetPreviewState(bool enabled)
		{
			object metaManager = GetMetaManager();
			if (metaManager != null && methodMetaCosmeticPreviewSet != null)
			{
				methodMetaCosmeticPreviewSet.Invoke(metaManager, new object[1] { enabled });
			}
		}

		private static void CopyEquippedToPreview()
		{
			object metaManager = GetMetaManager();
			if (metaManager == null)
			{
				return;
			}
			IList list = GetList(fieldMetaCosmeticEquipped, metaManager);
			IList list2 = GetList(fieldMetaCosmeticEquippedPreview, metaManager);
			if (list2 == null)
			{
				return;
			}
			list2.Clear();
			if (list != null)
			{
				foreach (object item in list)
				{
					list2.Add(item);
				}
			}
			int[] array = ((fieldMetaColorsEquipped != null) ? (fieldMetaColorsEquipped.GetValue(metaManager) as int[]) : null);
			int[] array2 = ((fieldMetaColorsEquippedPreview != null) ? (fieldMetaColorsEquippedPreview.GetValue(metaManager) as int[]) : null);
			if (array != null && array2 != null)
			{
				int num = Mathf.Min(array.Length, array2.Length);
				for (int i = 0; i < num; i++)
				{
					array2[i] = array[i];
				}
			}
		}

		private static List<int> RemoveConflictingPreviewCosmetics(object metaManager, object cosmeticAsset, IList preview)
		{
			List<int> list = new List<int>();
			if (metaManager == null || cosmeticAsset == null || preview == null || methodMetaGetCosmeticsToUnequip == null)
			{
				return list;
			}
			int cosmeticIndex = GetCosmeticIndex(cosmeticAsset);
			List<int> list2 = ToIntList(preview);
			if (cosmeticIndex >= 0 && !list2.Contains(cosmeticIndex))
			{
				list2.Add(cosmeticIndex);
			}
			object obj = methodMetaGetCosmeticsToUnequip.Invoke(metaManager, new object[2] { list2, cosmeticAsset });
			if (!(obj is IEnumerable enumerable))
			{
				return list;
			}
			foreach (object item in enumerable)
			{
				int cosmeticIndex2 = GetCosmeticIndex(item);
				if (cosmeticIndex2 >= 0 && cosmeticIndex2 != cosmeticIndex)
				{
					ListRemoveInt(preview, cosmeticIndex2);
					list.Add(cosmeticIndex2);
				}
			}
			return list;
		}

		private static void ApplyDefaultColorToPreview(object metaManager, object cosmeticAsset)
		{
			if (metaManager == null || cosmeticAsset == null || fieldCosmeticType == null || fieldMetaColorsEquippedPreview == null || !(fieldMetaColorsEquippedPreview.GetValue(metaManager) is int[] array))
			{
				return;
			}
			int num = Convert.ToInt32(fieldCosmeticType.GetValue(cosmeticAsset));
			if (num < 0 || num >= array.Length)
			{
				return;
			}
			int num2 = 0;
			object obj = ((fieldCosmeticDefaultColor != null) ? fieldCosmeticDefaultColor.GetValue(cosmeticAsset) : null);
			IList list = GetList(fieldMetaColors, metaManager);
			if (obj != null && list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i] == obj)
					{
						num2 = i;
						break;
					}
				}
			}
			array[num] = num2;
		}

		private static void RemovePinnedTryOnIndex(int cosmeticIndex)
		{
			if (cosmeticIndex < 0)
			{
				return;
			}
			pinnedTryOnAssets.Remove(cosmeticIndex);
			for (int num = pinnedTryOnOrder.Count - 1; num >= 0; num--)
			{
				if (pinnedTryOnOrder[num] == cosmeticIndex)
				{
					pinnedTryOnOrder.RemoveAt(num);
				}
			}
		}

		private static void AddPinnedTryOnIndex(int cosmeticIndex, object cosmeticAsset)
		{
			if (cosmeticIndex >= 0 && cosmeticAsset != null)
			{
				if (!pinnedTryOnAssets.ContainsKey(cosmeticIndex))
				{
					pinnedTryOnOrder.Add(cosmeticIndex);
				}
				pinnedTryOnAssets[cosmeticIndex] = cosmeticAsset;
			}
		}

		private static bool RebuildTryOnPreview(object hoverAsset, int hoverIndex, bool includeHover)
		{
			try
			{
				object metaManager = GetMetaManager();
				if (metaManager == null)
				{
					return false;
				}
				CopyEquippedToPreview();
				IList list = GetList(fieldMetaCosmeticEquippedPreview, metaManager);
				if (list == null)
				{
					return false;
				}
				List<int> list2 = new List<int>(pinnedTryOnOrder);
				foreach (int item in list2)
				{
					if (!pinnedTryOnAssets.ContainsKey(item))
					{
						continue;
					}
					object obj = pinnedTryOnAssets[item];
					if (obj == null)
					{
						obj = GetCosmeticAssetByIndex(item);
						pinnedTryOnAssets[item] = obj;
					}
					if (obj == null || IsUnlocked(item))
					{
						RemovePinnedTryOnIndex(item);
						continue;
					}
					List<int> list3 = RemoveConflictingPreviewCosmetics(metaManager, obj, list);
					foreach (int item2 in list3)
					{
						if (item2 != item && pinnedTryOnAssets.ContainsKey(item2))
						{
							RemovePinnedTryOnIndex(item2);
						}
					}
					ListAddInt(list, item);
					ApplyDefaultColorToPreview(metaManager, obj);
				}
				if (includeHover && hoverAsset != null && hoverIndex >= 0 && !pinnedTryOnAssets.ContainsKey(hoverIndex))
				{
					RemoveConflictingPreviewCosmetics(metaManager, hoverAsset, list);
					ListAddInt(list, hoverIndex);
					ApplyDefaultColorToPreview(metaManager, hoverAsset);
				}
				tryOnPinned = pinnedTryOnOrder.Count > 0;
				hoverPreviewActive = includeHover && hoverAsset != null && hoverIndex >= 0 && !pinnedTryOnAssets.ContainsKey(hoverIndex);
				tryOnActive = tryOnPinned || hoverPreviewActive;
				currentLockedIndex = (includeHover ? hoverIndex : ((pinnedTryOnOrder.Count > 0) ? pinnedTryOnOrder[pinnedTryOnOrder.Count - 1] : (-1)));
				currentLockedAsset = (includeHover ? hoverAsset : ((currentLockedIndex >= 0 && pinnedTryOnAssets.ContainsKey(currentLockedIndex)) ? pinnedTryOnAssets[currentLockedIndex] : null));
				if (tryOnActive)
				{
					rebuildingTryOnPreview = true;
					try
					{
						SetPreviewState(enabled: true);
						RefreshLocalCosmetics(forced: false);
					}
					finally
					{
						rebuildingTryOnPreview = false;
					}
				}
				else
				{
					ClearTryOnPreview(forced: true);
				}
				return true;
			}
			catch (Exception ex)
			{
				WriteFailure("RebuildTryOnPreview", ex);
				return false;
			}
		}

		private static bool ApplyHoverLockedPreview(object cosmeticAsset, int cosmeticIndex)
		{
			try
			{
				if (!IsEnabled() || cosmeticAsset == null)
				{
					return false;
				}
				int num = ((cosmeticIndex >= 0) ? cosmeticIndex : GetCosmeticIndex(cosmeticAsset));
				if (num < 0 || IsUnlocked(num))
				{
					return false;
				}
				WriteDebug("Hover try-on preview applied: " + num);
				return RebuildTryOnPreview(cosmeticAsset, num, includeHover: true);
			}
			catch (Exception ex)
			{
				WriteFailure("ApplyHoverLockedPreview", ex);
				return false;
			}
		}

		private static bool TogglePinnedLockedPreview(object cosmeticAsset, int cosmeticIndex)
		{
			try
			{
				if (!IsEnabled() || cosmeticAsset == null)
				{
					return false;
				}
				int num = ((cosmeticIndex >= 0) ? cosmeticIndex : GetCosmeticIndex(cosmeticAsset));
				if (num < 0 || IsUnlocked(num))
				{
					return false;
				}
				if (pinnedTryOnAssets.ContainsKey(num))
				{
					RemovePinnedTryOnIndex(num);
					WriteDebug("Pinned try-on removed: " + num);
					return RebuildTryOnPreview(null, -1, includeHover: false);
				}
				AddPinnedTryOnIndex(num, cosmeticAsset);
				WriteDebug("Pinned try-on added: " + num);
				return RebuildTryOnPreview(null, -1, includeHover: false);
			}
			catch (Exception ex)
			{
				WriteFailure("TogglePinnedLockedPreview", ex);
				return false;
			}
		}

		private static bool ApplyLockedPreview(object cosmeticAsset, int cosmeticIndex, bool pinned)
		{
			if (pinned)
			{
				return TogglePinnedLockedPreview(cosmeticAsset, cosmeticIndex);
			}
			return ApplyHoverLockedPreview(cosmeticAsset, cosmeticIndex);
		}

		private static void ClearTryOnPreview(bool forced)
		{
			try
			{
				if (tryOnActive || forced)
				{
					forceClearingPreview = true;
					tryOnActive = false;
					tryOnPinned = false;
					hoverPreviewActive = false;
					currentLockedIndex = -1;
					currentLockedAsset = null;
					pinnedTryOnAssets.Clear();
					pinnedTryOnOrder.Clear();
					SetPreviewState(enabled: false);
					RefreshLocalCosmetics(forced);
				}
			}
			catch (Exception ex)
			{
				WriteFailure("ClearTryOnPreview", ex);
			}
			finally
			{
				forceClearingPreview = false;
			}
		}

		private static void SanitizeSaveTargets()
		{
			try
			{
				if (!IsEnabled())
				{
					return;
				}
				object metaManager = GetMetaManager();
				if (metaManager == null)
				{
					return;
				}
				IList list = GetList(fieldMetaCosmeticEquipped, metaManager);
				if (list != null)
				{
					foreach (int item in ToIntList(list))
					{
						if (item >= 0 && !IsUnlocked(item))
						{
							ListRemoveInt(list, item);
							WriteDebug("Removed locked cosmetic from equipped before save: " + item);
						}
					}
				}
				IList list2 = GetList(fieldMetaCosmeticPresets, metaManager);
				if (list2 == null)
				{
					return;
				}
				foreach (object item2 in list2)
				{
					if (!(item2 is IList list3))
					{
						continue;
					}
					foreach (int item3 in ToIntList(list3))
					{
						if (item3 >= 0 && !IsUnlocked(item3))
						{
							ListRemoveInt(list3, item3);
							WriteDebug("Removed locked cosmetic from preset before save: " + item3);
						}
					}
				}
			}
			catch (Exception ex)
			{
				WriteFailure("SanitizeSaveTargets", ex);
			}
		}

		private static void MarkLockedButton(object button)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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)
			try
			{
				if (!IsEnabled() || button == null)
				{
					return;
				}
				object buttonCosmeticAsset = GetButtonCosmeticAsset(button);
				int buttonCosmeticIndex = GetButtonCosmeticIndex(button);
				if (!IsLockedCosmetic(buttonCosmeticAsset, buttonCosmeticIndex))
				{
					HideTryMarker(button);
					return;
				}
				SetButtonDisabled(button, disabled: false);
				if (fieldButtonIconText != null)
				{
					TextMeshProUGUIBridge.SetText(fieldButtonIconText.GetValue(button), string.Empty);
				}
				SetOrCreateTryMarker(button);
				if (buttonCosmeticAsset != null && fieldButtonIconImage != null && methodCosmeticGetIcon != null)
				{
					object? value = fieldButtonIconImage.GetValue(button);
					Image val = (Image)((value is Image) ? value : null);
					object obj = methodCosmeticGetIcon.Invoke(buttonCosmeticAsset, null);
					Sprite val2 = (Sprite)((obj is Sprite) ? obj : null);
					if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
					{
						val.sprite = val2;
						((Graphic)val).color = new Color(1f, 1f, 1f, Mathf.Clamp01(0.85f));
						((Component)val).gameObject.SetActive(true);
					}
				}
				if (buttonCosmeticAsset != null && fieldButtonBgBorder != null && methodCosmeticGetRarityColor != null)
				{
					object? value2 = fieldButtonBgBorder.GetValue(button);
					RawImage val3 = (RawImage)((value2 is RawImage) ? value2 : null);
					object obj2 = methodCosmeticGetRarityColor.Invoke(buttonCosmeticAsset, null);
					if ((Object)(object)val3 != (Object)null && obj2 is Color val4)
					{
						Color color = val4 * 0.45f;
						color.a = val4.a;
						((Graphic)val3).color = color;
					}
				}
				if (fieldButtonTintableButton != null)
				{
					object value3 = fieldButtonTintableButton.GetValue(button);
					Component val5 = (Component)((value3 is Component) ? value3 : null);
					if ((Object)(object)val5 != (Object)null)
					{
						val5.gameObject.SetActive(false);
					}
				}
			}
			catch (Exception ex)
			{
				WriteFailure("MarkLockedButton", ex);
			}
		}

		private static void SetOrCreateTryMarker(object button)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_017a: 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_01c7: 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_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Component val = (Component)((button is Component) ? button : null);
				if (!((Object)(object)val == (Object)null))
				{
					Transform transform = val.transform;
					Transform val2 = transform.Find("REPOJP_CosmeticTryOn_TryMarker");
					GameObject val3;
					if ((Object)(object)val2 != (Object)null)
					{
						val3 = ((Component)val2).gameObject;
					}
					else
					{
						val3 = new GameObject("REPOJP_CosmeticTryOn_TryMarker", new Type[3]
						{
							typeof(RectTransform),
							typeof(Text),
							typeof(Outline)
						});
						val3.transform.SetParent(transform, false);
						RectTransform component = val3.GetComponent<RectTransform>();
						component.anchorMin = new Vector2(0.5f, 1f);
						component.anchorMax = new Vector2(0.5f, 1f);
						component.pivot = new Vector2(0.5f, 1f);
						component.sizeDelta = new Vector2(70f, 18f);
						component.anchoredPosition = new Vector2(0f, -3f);
						Text component2 = val3.GetComponent<Text>();
						((Graphic)component2).raycastTarget = false;
						component2.alignment = (TextAnchor)4;
						component2.fontSize = 13;
						component2.fontStyle = (FontStyle)1;
						component2.resizeTextForBestFit = true;
						component2.resizeTextMinSize = 9;
						component2.resizeTextMaxSize = 15;
						component2.horizontalOverflow = (HorizontalWrapMode)1;
						component2.verticalOverflow = (VerticalWrapMode)1;
						component2.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
						Outline component3 = val3.GetComponent<Outline>();
						((Shadow)component3).effectColor = new Color(0f, 0f, 0f, 0.85f);
						((Shadow)component3).effectDistance = new Vector2(1.5f, -1.5f);
						((Shadow)component3).useGraphicAlpha = false;
					}
					RectTransform component4 = val3.GetComponent<RectTransform>();
					if ((Object)(object)component4 != (Object)null)
					{
						((Transform)component4).SetAsLastSibling();
						component4.anchorMin = new Vector2(0.5f, 1f);
						component4.anchorMax = new Vector2(0.5f, 1f);
						component4.pivot = new Vector2(0.5f, 1f);
						component4.sizeDelta = new Vector2(70f, 18f);
						component4.anchoredPosition = new Vector2(0f, -3f);
					}
					Text component5 = val3.GetComponent<Text>();
					if ((Object)(object)component5 != (Object)null)
					{
						int buttonCosmeticIndex = GetButtonCosmeticIndex(button);
						component5.text = (pinnedTryOnAssets.ContainsKey(buttonCosmeticIndex) ? "ON" : "TRY");
						((Graphic)component5).color = Color.white;
					}
					val3.SetActive(true);
				}
			}
			catch (Exception ex)
			{
				WriteFailure("SetOrCreateTryMarker", ex);
			}
		}

		private static void HideTryMarker(object button)
		{
			try
			{
				Component val = (Component)((button is Component) ? button : null);
				if (!((Object)(object)val == (Object)null))
				{
					Transform val2 = val.transform.Find("REPOJP_CosmeticTryOn_TryMarker");
					if ((Object)(object)val2 != (Object)null)
					{
						((Component)val2).gameObject.SetActive(false);
					}
				}
			}
			catch (Exception ex)
			{
				WriteFailure("HideTryMarker", ex);
			}
		}

		private static bool MetaManager_CosmeticEquip_Prefix(object __instance, object _cosmeticAssetNew, bool _isPreview, bool _save, ref bool __result)
		{
			try
			{
				if (!IsEnabled() || forceClearingPreview || !_isPreview || _cosmeticAssetNew == null)
				{
					return true;
				}
				int cosmeticIndex = GetCosmeticIndex(_cosmeticAssetNew);
				if (cosmeticIndex < 0 || IsUnlocked(cosmeticIndex))
				{
					return true;
				}
				__result = ApplyLockedPreview(_cosmeticAssetNew, cosmeticIndex, pinned: false);
				return false;
			}
			catch (Exception ex)
			{
				WriteFailure("MetaManager.CosmeticEquip", ex);
				return true;
			}
		}

		private static bool MetaManager_CosmeticPreviewSet_Prefix(bool _state)
		{
			try
			{
				if (!IsEnabled() || forceClearingPreview)
				{
					return true;
				}
				if (_state && pinnedTryOnOrder.Count > 0 && !rebuildingTryOnPreview)
				{
					RebuildTryOnPreview(null, -1, includeHover: false);
					return false;
				}
				if (!_state && pinnedTryOnOrder.Count > 0)
				{
					RebuildTryOnPreview(null, -1, includeHover: false);
					return false;
				}
				if (!_state && tryOnActive && !tryOnPinned)
				{
					hoverPreviewActive = false;
					tryOnActive = false;
					currentLockedIndex = -1;
					currentLockedAsset = null;
				}
				return true;
			}
			catch (Exception ex)
			{
				WriteFailure("MetaManager.CosmeticPreviewSet", ex);
				return true;
			}
		}

		private static void MetaManager_Save_Prefix()
		{
			SanitizeSaveTargets();
		}

		private static void MenuElementCosmeticButton_Start_Postfix(object __instance)
		{
			try
			{
				if (IsEnabled())
				{
					MarkLockedButton(__instance);
					InvokeButtonUpdateIcon(__instance, initial: true);
					MarkLockedButton(__instance);
				}
			}
			catch (Exception ex)
			{
				WriteFailure("MenuElementCosmeticButton.Start", ex);
			}
		}

		private static void MenuElementCosmeticButton_UpdateIcon_Postfix(object __instance)
		{
			MarkLockedButton(__instance);
		}

		private static bool MenuElementCosmeticButton_ToggleCosmetic_Prefix(object __instance)
		{
			try
			{
				if (!IsEnabled() || __instance == null)
				{
					return true;
				}
				object buttonCosmeticAsset = GetButtonCosmeticAsset(__instance);
				int buttonCosmeticIndex = GetButtonCosmeticIndex(__instance);
				if (!IsLockedCosmetic(buttonCosmeticAsset, buttonCosmeticIndex))
				{
					return true;
				}
				TogglePinnedLockedPreview(buttonCosmeticAsset, buttonCosmeticIndex);
				return false;
			}
			catch (Exception ex)
			{
				WriteFailure("MenuElementCosmeticButton.ToggleCosmetic", ex);
				return true;
			}
		}

		private static void MenuPageCosmetics_ConfirmButton_Prefix()
		{
			ClearTryOnPreview(forced: true);
		}

		private static void MenuPageCosmetics_OnDestroy_Postfix()
		{
			ClearTryOnPreview(forced: true);
		}

		private static void RunManager_ChangeLevel_Prefix()
		{
			ClearTryOnPreview(forced: true);
		}

		private static void LevelGenerator_GenerateDone_Postfix()
		{
			ClearTryOnPreview(forced: true);
		}
	}
}