Decompiled source of Custom Cosmetics Framework v2.0.0

Mods/CosmeticFramework.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.InteropServices;
using System.Runtime.Versioning;
using System.Text.Json;
using CosmeticFramework;
using CustomCosmeticsFW;
using HarmonyLib;
using Il2Cpp;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using MelonLoader;
using Microsoft.CodeAnalysis;
using NeckBreakingMod;
using Newtonsoft.Json;
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: MelonInfo(typeof(Main), "Cosmetic Framework", "2.0.0", "BekoniX", null)]
[assembly: MelonGame("Kubunautilus", "BrutalistickVR")]
[assembly: AssemblyTitle("CosmeticFramework")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CosmeticFramework")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8c5cf839-fb45-4c19-b329-39d7307605a8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NeckBreakingMod
{
	public class Main : MelonMod
	{
		public static class CustomCosmeticEnum
		{
			public const int UpperBody = 4;
		}

		[HarmonyPatch(typeof(PlayerCosmeticsData), "SaveCosmeticsData")]
		public static class PatchSave
		{
			public static bool Prefix(PlayerCosmeticsData __instance)
			{
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Expected O, but got Unknown
				//IL_0129: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: 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)
				if (!CanSave)
				{
					MelonCoroutines.Start(DelayCosmeticSave());
					return false;
				}
				List<PlayerCosmetic> list = new List<PlayerCosmetic>();
				list.Clear();
				Enumerator<PlayerCosmetic> enumerator = __instance.loadedCosmeticsData.GetEnumerator();
				while (enumerator.MoveNext())
				{
					PlayerCosmetic current = enumerator.Current;
					if (current.Description.Contains("Modded Cosmetic"))
					{
						CosmeticSaver.SettingsManager.SaveProfile(current.Name, new CosmeticSaver.CosmeticData
						{
							Description = current.Description,
							unlockStatus = current.unlockStatus,
							isEquipped = current.isEquipped
						});
						list.Add(current);
					}
				}
				foreach (PlayerCosmetic item in list)
				{
					PlayerCosmetic val = new PlayerCosmetic();
					val.Name = item.Name;
					val.Description = item.Description;
					val.Price = item.Price;
					val.unlockStatus = item.unlockStatus;
					val.isEquipped = item.isEquipped;
					val.Prefab = item.Prefab;
					val.Type = item.Type;
					val.Sprite = item.Sprite;
					val.primaryColor = item.primaryColor;
					val.accentColor = item.accentColor;
					val.accentContainsAlpha = item.accentContainsAlpha;
					__instance.loadedCosmeticsData.Remove(item);
					MelonCoroutines.Start(AddCosmetic(val));
				}
				CanSave = false;
				return true;
			}

			public static void Postfix(PlayerCosmeticsData __instance)
			{
				if (SceneLoaded)
				{
					MelonCoroutines.Start(DelayedGenerate());
				}
			}
		}

		[HarmonyPatch(typeof(CosmeticsWall), "FocusCosmetic")]
		public static class PatchFocus
		{
			public static void Postfix(CosmeticsWall __instance, int cosmeticIndex)
			{
				LastFocusedIndex = cosmeticIndex;
			}
		}

		[HarmonyPatch(typeof(CosmeticsWall), "EquipCosmetic")]
		public static class PatchEquip
		{
			public static void Prefix(CosmeticsWall __instance, int cosmeticIndex)
			{
			}
		}

		private bool LoadedBundles = false;

		private static bool FinishedBundles;

		private static bool SceneLoaded;

		private static float SceneLoadTime;

		private static ScrollRect SpawnMenuScrollRect;

		private static GameObject ItemMenu;

		private static RectTransform ItemMenuRect;

		public static GameObject CosmeticsMenu;

		public static int LastFocusedIndex;

		private static bool UIGenerated;

		private static bool UIRefreshed;

		public static GameObject PlrCosmeticsData;

		private static bool CanSave;

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (!(sceneName != "MainMenuScene"))
			{
				return;
			}
			CosmeticsMenu = GameObject.Find("DressingRoom/DressingMenu");
			GameObject[] array = Il2CppArrayBase<GameObject>.op_Implicit(Object.FindObjectsOfType<GameObject>());
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				if (((Object)(object)val != (Object)null && ((Object)val).name == "Hexa4Rig26.10.23") || ((Object)val).name == "Hexa4Rig26.10.23(Clone)")
				{
				}
				if (((Object)val).name == "PlayerCosmeticsData")
				{
					PlrCosmeticsData = val;
				}
			}
			SceneLoaded = true;
			SceneLoadTime = Time.time;
		}

		public override void OnUpdate()
		{
			if (!SceneLoaded || !(Time.time - SceneLoadTime > 0.5f))
			{
				return;
			}
			if (!LoadedBundles)
			{
				List<AssetBundle> list = CheckBundles();
				LoadedBundles = true;
				if (list != null && list.Count != 0)
				{
					LoadBundles(list);
				}
			}
			if (LoadedBundles && FinishedBundles && !UIGenerated)
			{
				UIGenerated = true;
				RefreshUI(focus: false);
				GenerateUI();
			}
		}

		public static void SetupCosmetic(GameObject CosmeticPrefab, TextAsset CosmeticData, Il2CppReferenceArray<Object> BundleAssets)
		{
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			CosmeticPrefab = Object.Instantiate<GameObject>(CosmeticPrefab);
			CosmeticItem val = CosmeticPrefab.AddComponent<CosmeticItem>();
			((Object)CosmeticPrefab).hideFlags = (HideFlags)61;
			foreach (MeshRenderer componentsInChild in CosmeticPrefab.GetComponentsInChildren<MeshRenderer>())
			{
				foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)componentsInChild).materials)
				{
					if (((Object)item.shader).name == "Universal Render Pipeline/Lit" || ((Object)item.shader).name == "Universal Render Pipeline/Unlit")
					{
						item.shader = Shader.Find("Shader Graphs/PaintCel2");
					}
				}
			}
			DataCosmetic dataCosmetic = JsonConvert.DeserializeObject<DataCosmetic>(CosmeticData.text);
			Sprite sprite = null;
			foreach (Object item2 in (Il2CppArrayBase<Object>)(object)BundleAssets)
			{
				Sprite val2 = ((Il2CppObjectBase)item2).TryCast<Sprite>();
				if ((Object)(object)val2 != (Object)null && item2.name == dataCosmetic.icon)
				{
					sprite = ((Il2CppObjectBase)item2).Cast<Sprite>();
				}
			}
			List<GameObject> list = new List<GameObject>();
			list.Add(CosmeticPrefab);
			IEnumerator enumerator4 = CosmeticPrefab.transform.GetEnumerator();
			try
			{
				while (enumerator4.MoveNext())
				{
					Object current4 = enumerator4.Current;
					Transform val3 = ((Il2CppObjectBase)current4).Cast<Transform>();
					list.Add(((Component)val3).gameObject);
				}
			}
			finally
			{
				if (enumerator4 is IDisposable disposable)
				{
					disposable.Dispose();
				}
			}
			Il2CppReferenceArray<GameObject> extraLayersToSet = new Il2CppReferenceArray<GameObject>(list.ToArray());
			val.extraLayersToSet = extraLayersToSet;
			val.hideWhenWorn = true;
			PlayerCosmetic val4 = new PlayerCosmetic();
			val4.Sprite = sprite;
			val4.Name = dataCosmetic.name;
			val4.Description = "Modded Cosmetic: " + dataCosmetic.description;
			val4.Price = dataCosmetic.price;
			val4.unlockStatus = 1;
			val4.isEquipped = false;
			val4.Prefab = CosmeticPrefab;
			val4.primaryColor = Color.white;
			val4.accentColor = Color.white;
			val4.accentContainsAlpha = false;
			val.cosmeticName = dataCosmetic.name;
			val.cosmeticDescription = "Modded Cosmetic: " + dataCosmetic.description;
			val.primaryColor = Color.white;
			val.accentColor = Color.white;
			if (dataCosmetic.type == "Head")
			{
				val4.Type = (CosmeticType)0;
				val.cosmeticType = (CosmeticType)0;
			}
			if (dataCosmetic.type == "UpperBody")
			{
				val4.Type = (CosmeticType)4;
				val.cosmeticType = (CosmeticType)4;
			}
			List<CosmeticSaver.CosmeticProfile> list2 = CosmeticSaver.SettingsManager.LoadProfiles();
			foreach (CosmeticSaver.CosmeticProfile item3 in list2)
			{
				if (item3.ProfileName == val4.Name)
				{
					CosmeticSaver.CosmeticData cosmeticData = CosmeticSaver.SettingsManager.LoadProfile(item3.ProfileName);
					val4.unlockStatus = cosmeticData.unlockStatus;
					val4.isEquipped = cosmeticData.isEquipped;
					if (cosmeticData.isEquipped)
					{
						flag = true;
					}
				}
			}
			Enumerator<PlayerCosmetic> enumerator6 = PlrCosmeticsData.GetComponent<PlayerCosmeticsData>().loadedCosmeticsData.GetEnumerator();
			while (enumerator6.MoveNext())
			{
				PlayerCosmetic current6 = enumerator6.Current;
				if (current6.Name == val4.Name && current6.Description == val4.Description)
				{
					val4.unlockStatus = current6.unlockStatus;
					val4.isEquipped = current6.isEquipped;
				}
			}
			PlayerCosmeticsData component = PlrCosmeticsData.GetComponent<PlayerCosmeticsData>();
			component.loadedCosmeticsData.Add(val4);
			component.headCosmetics.Add(val4);
			if (flag)
			{
				int num = component.loadedCosmeticsData.IndexOf(val4);
				if ((Object)(object)CosmeticsMenu != (Object)null)
				{
					CosmeticsWall component2 = CosmeticsMenu.GetComponent<CosmeticsWall>();
					component2.EquipCosmetic(num);
				}
			}
		}

		private static IEnumerator ReturnToListViewSafely(CosmeticsWall CosmeticsWallComponent)
		{
			yield return (object)new WaitForSeconds(0.1f);
			CosmeticsWallComponent.returnToListViewButton.Press();
		}

		public static void LoadBundles(List<AssetBundle> bundleArray)
		{
			foreach (AssetBundle item in bundleArray)
			{
				Il2CppReferenceArray<Object> val = item.LoadAllAssets();
				GameObject val2 = null;
				TextAsset val3 = null;
				foreach (Object item2 in (Il2CppArrayBase<Object>)(object)val)
				{
					GameObject val4 = ((Il2CppObjectBase)item2).TryCast<GameObject>();
					if ((Object)(object)val4 != (Object)null && ((Object)val4).name != "BodyTemplate" && Object.op_Implicit((Object)(object)val4.GetComponent<Rigidbody>()))
					{
						val2 = val4;
					}
					TextAsset val5 = ((Il2CppObjectBase)item2).TryCast<TextAsset>();
					if ((Object)(object)val5 != (Object)null && ((Object)val5).name == "CosmeticData")
					{
						val3 = val5;
					}
				}
				if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
				{
					SetupCosmetic(val2, val3, val);
				}
			}
			FinishedBundles = true;
			MelonCoroutines.Start(ReturnToListViewSafely(CosmeticsMenu.GetComponent<CosmeticsWall>()));
		}

		public static List<AssetBundle> CheckBundles()
		{
			List<AssetBundle> list = new List<AssetBundle>();
			Il2CppArrayBase<AssetBundle> val = MonoLinqHelper.ToArray<AssetBundle>(AssetBundle.GetAllLoadedAssetBundles());
			foreach (AssetBundle item in val)
			{
				if (((IEnumerable<string>)item.AllAssetNames()).Any((string p) => Path.GetFileNameWithoutExtension(p) == "cosmeticdata"))
				{
					list.Add(item);
				}
			}
			return list;
		}

		private static IEnumerator SetPositionNextFrame()
		{
			yield return (object)new WaitForEndOfFrame();
			Vector3 startPos = new Vector3(-2.797f, -0.3f, 0f);
			float rowSpacing = 0.8f;
			int i = 0;
			while (true)
			{
				Transform val;
				Transform row = (val = ItemMenu.transform.Find("ItemRow" + i));
				if ((Object)(object)val != (Object)null)
				{
					row.localPosition = startPos - new Vector3(0f, rowSpacing * (float)i, 0f);
					i++;
					continue;
				}
				break;
			}
		}

		public static void GenerateUI()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = GameObject.Find("DressingRoom/DressingMenu/DressingCanvas/ListView").transform;
			SpawnMenuScrollRect = ((Component)transform.Find("SpawnMenuScroll")).GetComponent<ScrollRect>();
			ItemMenu = ((Component)transform.Find("ScrollViewRect/ItemMenu")).gameObject;
			ItemMenuRect = ((Component)transform.Find("ScrollViewRect/ItemMenu")).GetComponent<RectTransform>();
			if ((Object)(object)SpawnMenuScrollRect != (Object)null && (Object)(object)ItemMenu != (Object)null && (Object)(object)ItemMenuRect != (Object)null)
			{
				SpawnMenuScrollRect.content = ItemMenuRect;
				ItemMenuRect.sizeDelta = new Vector2(100f, 10f);
				MelonCoroutines.Start(SetPositionNextFrame());
			}
		}

		public static void RefreshUI(bool focus)
		{
			if (!((Object)(object)CosmeticsMenu == (Object)null))
			{
				CosmeticsMenu.GetComponent<CosmeticsWall>().RefreshSpawnMenu("all");
				if (focus)
				{
					CosmeticsMenu.GetComponent<CosmeticsWall>().FocusCosmetic(LastFocusedIndex);
				}
				UIRefreshed = true;
			}
		}

		public static IEnumerator DelayedGenerate()
		{
			yield return (object)new WaitForSeconds(0.1f);
			RefreshUI(focus: true);
			GenerateUI();
		}

		public static IEnumerator AddCosmetic(PlayerCosmetic data)
		{
			yield return (object)new WaitForSeconds(0.1f);
			PlrCosmeticsData.GetComponent<PlayerCosmeticsData>().loadedCosmeticsData.Add(data);
		}

		public static IEnumerator DelayCosmeticSave()
		{
			yield return (object)new WaitForEndOfFrame();
			CanSave = true;
			PlrCosmeticsData.GetComponent<PlayerCosmeticsData>().SaveCosmeticsData();
		}
	}
}
namespace CosmeticFramework
{
	public class DataCosmetic
	{
		public string type;

		public string name;

		public string description;

		public int price;

		public string icon;
	}
}
namespace CustomCosmeticsFW
{
	public static class CosmeticSaver
	{
		public class CosmeticData
		{
			public string Description { get; set; } = "";

			public int unlockStatus { get; set; } = 1;

			public bool isEquipped { get; set; } = false;
		}

		public class CosmeticProfile
		{
			public string ProfileName { get; set; } = "Default";

			public CosmeticData Settings { get; set; } = new CosmeticData();
		}

		public static class SettingsManager
		{
			private static string path = "Mods/CosmeticsFramework/ModCosmeticData.json";

			public static void SaveProfiles(List<CosmeticProfile> profiles)
			{
				Directory.CreateDirectory(Path.GetDirectoryName(path));
				string contents = JsonSerializer.Serialize(profiles, new JsonSerializerOptions
				{
					WriteIndented = true
				});
				File.WriteAllText(path, contents);
			}

			public static List<CosmeticProfile> LoadProfiles()
			{
				if (!File.Exists(path))
				{
					Directory.CreateDirectory(Path.GetDirectoryName(path));
					List<CosmeticProfile> list = new List<CosmeticProfile>
					{
						new CosmeticProfile
						{
							ProfileName = "Default",
							Settings = new CosmeticData()
						}
					};
					SaveProfiles(list);
					return list;
				}
				try
				{
					string json = File.ReadAllText(path);
					return JsonSerializer.Deserialize<List<CosmeticProfile>>(json) ?? new List<CosmeticProfile>();
				}
				catch
				{
					return new List<CosmeticProfile>();
				}
			}

			public static void SaveProfile(string name, CosmeticData settings)
			{
				List<CosmeticProfile> list = LoadProfiles();
				CosmeticProfile cosmeticProfile = list.FirstOrDefault((CosmeticProfile p) => p.ProfileName.Equals(name, StringComparison.OrdinalIgnoreCase));
				if (cosmeticProfile != null)
				{
					cosmeticProfile.Settings = settings;
				}
				else
				{
					list.Add(new CosmeticProfile
					{
						ProfileName = name,
						Settings = settings
					});
				}
				SaveProfiles(list);
			}

			public static CosmeticData LoadProfile(string name)
			{
				List<CosmeticProfile> source = LoadProfiles();
				return source.FirstOrDefault((CosmeticProfile p) => p.ProfileName.Equals(name, StringComparison.OrdinalIgnoreCase))?.Settings ?? new CosmeticData();
			}
		}
	}
}