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 list = new List(); list.Clear(); Enumerator 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.op_Implicit(Object.FindObjectsOfType()); 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 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 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(CosmeticPrefab); CosmeticItem val = CosmeticPrefab.AddComponent(); ((Object)CosmeticPrefab).hideFlags = (HideFlags)61; foreach (MeshRenderer componentsInChild in CosmeticPrefab.GetComponentsInChildren()) { foreach (Material item in (Il2CppArrayBase)(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(CosmeticData.text); Sprite sprite = null; foreach (Object item2 in (Il2CppArrayBase)(object)BundleAssets) { Sprite val2 = ((Il2CppObjectBase)item2).TryCast(); if ((Object)(object)val2 != (Object)null && item2.name == dataCosmetic.icon) { sprite = ((Il2CppObjectBase)item2).Cast(); } } List list = new List(); list.Add(CosmeticPrefab); IEnumerator enumerator4 = CosmeticPrefab.transform.GetEnumerator(); try { while (enumerator4.MoveNext()) { Object current4 = enumerator4.Current; Transform val3 = ((Il2CppObjectBase)current4).Cast(); list.Add(((Component)val3).gameObject); } } finally { if (enumerator4 is IDisposable disposable) { disposable.Dispose(); } } Il2CppReferenceArray extraLayersToSet = new Il2CppReferenceArray(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 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 enumerator6 = PlrCosmeticsData.GetComponent().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(); 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(); component2.EquipCosmetic(num); } } } private static IEnumerator ReturnToListViewSafely(CosmeticsWall CosmeticsWallComponent) { yield return (object)new WaitForSeconds(0.1f); CosmeticsWallComponent.returnToListViewButton.Press(); } public static void LoadBundles(List bundleArray) { foreach (AssetBundle item in bundleArray) { Il2CppReferenceArray val = item.LoadAllAssets(); GameObject val2 = null; TextAsset val3 = null; foreach (Object item2 in (Il2CppArrayBase)(object)val) { GameObject val4 = ((Il2CppObjectBase)item2).TryCast(); if ((Object)(object)val4 != (Object)null && ((Object)val4).name != "BodyTemplate" && Object.op_Implicit((Object)(object)val4.GetComponent())) { val2 = val4; } TextAsset val5 = ((Il2CppObjectBase)item2).TryCast(); 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())); } public static List CheckBundles() { List list = new List(); Il2CppArrayBase val = MonoLinqHelper.ToArray(AssetBundle.GetAllLoadedAssetBundles()); foreach (AssetBundle item in val) { if (((IEnumerable)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(); ItemMenu = ((Component)transform.Find("ScrollViewRect/ItemMenu")).gameObject; ItemMenuRect = ((Component)transform.Find("ScrollViewRect/ItemMenu")).GetComponent(); 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().RefreshSpawnMenu("all"); if (focus) { CosmeticsMenu.GetComponent().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().loadedCosmeticsData.Add(data); } public static IEnumerator DelayCosmeticSave() { yield return (object)new WaitForEndOfFrame(); CanSave = true; PlrCosmeticsData.GetComponent().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 profiles) { Directory.CreateDirectory(Path.GetDirectoryName(path)); string contents = JsonSerializer.Serialize(profiles, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(path, contents); } public static List LoadProfiles() { if (!File.Exists(path)) { Directory.CreateDirectory(Path.GetDirectoryName(path)); List list = new List { new CosmeticProfile { ProfileName = "Default", Settings = new CosmeticData() } }; SaveProfiles(list); return list; } try { string json = File.ReadAllText(path); return JsonSerializer.Deserialize>(json) ?? new List(); } catch { return new List(); } } public static void SaveProfile(string name, CosmeticData settings) { List 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 source = LoadProfiles(); return source.FirstOrDefault((CosmeticProfile p) => p.ProfileName.Equals(name, StringComparison.OrdinalIgnoreCase))?.Settings ?? new CosmeticData(); } } } }