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();
}
}
}
}