The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of CosmeticResync v1.0.0
plugins/CosmeticResync.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using CosmeticResync.Patches; using HarmonyLib; using Newtonsoft.Json; using UnityEngine; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("CosmeticResync")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CosmeticResync")] [assembly: AssemblyCopyright("Copyright © BlueAmulet 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("eb3c5a88-48ff-431d-9961-15eee8223f66")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace CosmeticResync { [BepInPlugin("BlueAmulet.CosmeticResync", "CosmeticResync", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class CosmeticResync : BaseUnityPlugin { internal const string Name = "CosmeticResync"; internal const string Author = "BlueAmulet"; internal const string ID = "BlueAmulet.CosmeticResync"; internal const string Version = "1.0.0"; internal static ManualLogSource Logger; public void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Harmony val = new Harmony("BlueAmulet.CosmeticResync"); Logger.LogInfo((object)"Applying Harmony patches"); val.PatchAll(Assembly.GetExecutingAssembly()); if (Chainloader.PluginInfos.TryGetValue("com.github.Spider-XD-Gaming.Multi-Cosmetic", out var value)) { MultiCosmeticPatch.MultiCosmetic = value.Instance; if (MultiCosmeticPatch.GetCurrentDataField()) { Type type = ((object)value.Instance).GetType(); MethodInfo methodInfo = AccessTools.Method(type, "dataFromString", (Type[])null, (Type[])null); if (methodInfo != null) { val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(MultiCosmeticPatch), "PrefixMCDataFromString", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Logger.LogError((object)"Failed to find Multi_Cosmetic.Plugin.dataFromString()"); } methodInfo = AccessTools.Method(type, "UpdateCustomPropertiesValue", (Type[])null, (Type[])null); if (methodInfo != null) { val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(MultiCosmeticPatch), "PostfixUpdateCustomPropertiesValue", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Logger.LogError((object)"Failed to find Multi_Cosmetic.Plugin.UpdateCustomPropertiesValue()"); } } } int num = 0; foreach (MethodBase patchedMethod in val.GetPatchedMethods()) { Logger.LogInfo((object)("Patched " + patchedMethod.DeclaringType.FullName + "." + patchedMethod.Name)); num++; } Logger.LogInfo((object)(num + " patches applied")); } } } namespace CosmeticResync.Patches { [HarmonyPatch(typeof(CharacterCustomization))] internal static class CosmeticPatch { [HarmonyPrefix] [HarmonyPatch("TryGetCosmeticsFromSteam")] private static bool PrefixTryGetCosmeticsFromSteam(ref CharacterCustomization __instance) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot Resync cosmetics"); return true; } int cosmeticFromPrefsOrSteam = GetCosmeticFromPrefsOrSteam("CosmeticResync_Skin", (STEAMSTATTYPE)7, instance.skins); if (cosmeticFromPrefsOrSteam > 0) { CharacterCustomization.SetCharacterSkinColor(cosmeticFromPrefsOrSteam); } else { __instance.SetRandomSkinColor(); } int cosmeticFromPrefsOrSteam2 = GetCosmeticFromPrefsOrSteam("CosmeticResync_Eyes", (STEAMSTATTYPE)8, instance.eyes); if (cosmeticFromPrefsOrSteam2 > 0) { CharacterCustomization.SetCharacterEyes(cosmeticFromPrefsOrSteam2); } else { __instance.SetRandomEyes(); } int cosmeticFromPrefsOrSteam3 = GetCosmeticFromPrefsOrSteam("CosmeticResync_Mouth", (STEAMSTATTYPE)9, instance.mouths); if (cosmeticFromPrefsOrSteam3 > 0) { CharacterCustomization.SetCharacterMouth(cosmeticFromPrefsOrSteam3); } else { __instance.SetRandomMouth(); } int cosmeticFromPrefsOrSteam4 = GetCosmeticFromPrefsOrSteam("CosmeticResync_Accessory", (STEAMSTATTYPE)10, instance.accessories); if (cosmeticFromPrefsOrSteam4 > 0) { CharacterCustomization.SetCharacterAccessory(cosmeticFromPrefsOrSteam4); } else { __instance.SetRandomAccessory(); } int cosmeticFromPrefsOrSteam5 = GetCosmeticFromPrefsOrSteam("CosmeticResync_Outfit", (STEAMSTATTYPE)11, instance.fits); if (cosmeticFromPrefsOrSteam5 > 0) { CharacterCustomization.SetCharacterOutfit(cosmeticFromPrefsOrSteam5); } else { __instance.SetRandomOutfit(); } int cosmeticFromPrefsOrSteam6 = GetCosmeticFromPrefsOrSteam("CosmeticResync_Hat", (STEAMSTATTYPE)12, instance.hats); if (cosmeticFromPrefsOrSteam6 > 0) { CharacterCustomization.SetCharacterHat(cosmeticFromPrefsOrSteam6); } else { __instance.SetRandomHat(); } int cosmeticFromPrefsOrSteam7 = GetCosmeticFromPrefsOrSteam("CosmeticResync_Sash", (STEAMSTATTYPE)17, instance.sashes); if (cosmeticFromPrefsOrSteam7 > 0) { CharacterCustomization.SetCharacterSash(cosmeticFromPrefsOrSteam7); } else { CharacterCustomization.SetCharacterSash(0); } return false; } [HarmonyPostfix] [HarmonyPatch("SetCharacterSkinColor")] private static void PostfixSetCharacterSkinColor(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save skin color"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Skin", instance.skins); } } [HarmonyPostfix] [HarmonyPatch("SetCharacterEyes")] private static void PostfixSetCharacterEyes(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save eyes"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Eyes", instance.eyes); } } [HarmonyPostfix] [HarmonyPatch("SetCharacterMouth")] private static void PostfixSetCharacterMouth(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save mouth"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Mouth", instance.mouths); } } [HarmonyPostfix] [HarmonyPatch("SetCharacterAccessory")] private static void PostfixSetCharacterAccessory(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save accessory name"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Accessory", instance.accessories); } } [HarmonyPostfix] [HarmonyPatch("SetCharacterOutfit")] private static void PostfixSetCharacterOutfit(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save outfit name"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Outfit", instance.fits); } } [HarmonyPostfix] [HarmonyPatch("SetCharacterHat")] private static void PostfixSetCharacterHat(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save hat name"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Hat", instance.hats); } } [HarmonyPostfix] [HarmonyPatch("SetCharacterSash")] private static void PostfixSetCharacterSash(int index) { Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save sash name"); } else { ValidateAndSaveCosmetic(index, "CosmeticResync_Sash", instance.sashes); } } private static int GetCosmeticFromPrefsOrSteam(string prefKey, STEAMSTATTYPE steamStatType, CustomizationOption[] options) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) int num = -1; if (PlayerPrefs.HasKey(prefKey)) { string @string = PlayerPrefs.GetString(prefKey); if (!string.IsNullOrWhiteSpace(@string)) { for (int i = 0; i < options.Length; i++) { if (((Object)options[i]).name == @string) { num = i; break; } } if (num != -1) { Debug.Log((object)$"[CosmeticResync] Detected {steamStatType} {@string} as #{num}"); } else { CosmeticResync.Logger.LogWarning((object)$"{steamStatType} {@string} is no longer available, picking a random option"); } } } else if (Singleton<AchievementManager>.Instance.GetSteamStatInt(steamStatType, ref num)) { if (num >= options.Length) { num = -1; } } else { num = -1; } return num; } private static void ValidateAndSaveCosmetic(int index, string prefKey, CustomizationOption[] options) { if (index < 0 || index >= options.Length) { CosmeticResync.Logger.LogError((object)$"Customization index #{index} invalid? Cannot save customization for {prefKey}"); } else { PlayerPrefs.SetString(prefKey, ((Object)options[index]).name); } } } [HarmonyPatch] internal static class MultiCosmeticPatch { internal static BaseUnityPlugin MultiCosmetic; private static FieldInfo _currentData; internal static bool GetCurrentDataField() { if ((Object)(object)MultiCosmetic == (Object)null) { CosmeticResync.Logger.LogError((object)"Missing MultiCosmetic instance"); return false; } FieldInfo fieldInfo = AccessTools.Field(((object)MultiCosmetic).GetType(), "currentData"); if (fieldInfo == null) { CosmeticResync.Logger.LogError((object)"MultiCosmetic missing currentData field"); return false; } if (fieldInfo.FieldType != typeof(int[][])) { CosmeticResync.Logger.LogError((object)"MultiCosmetic.currentData is no longer an int[][]"); return false; } _currentData = fieldInfo; return true; } internal static bool PrefixMCDataFromString() { if ((Object)(object)MultiCosmetic == (Object)null) { CosmeticResync.Logger.LogError((object)"Missing MultiCosmetic instance, cannot resync MultiCosmetic"); return true; } Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized, cannot resync MultiCosmetic"); return true; } if (!PlayerPrefs.HasKey("CosmeticResync_MultiCosmetic")) { return true; } string @string = PlayerPrefs.GetString("CosmeticResync_MultiCosmetic"); if (string.IsNullOrWhiteSpace(@string)) { CosmeticResync.Logger.LogWarning((object)"CosmeticResync_MultiCosmetic has no data, nothing to resync"); return true; } try { string[][] array = JsonConvert.DeserializeObject<string[][]>(@string); if (array.Length != 2) { CosmeticResync.Logger.LogWarning((object)$"CosmeticResync_MultiCosmetic is malformed, expected 2 arrays, got {array.Length}"); return true; } int[] cosmeticIndices = GetCosmeticIndices(instance.accessories, array[0], "Accessory"); int[] cosmeticIndices2 = GetCosmeticIndices(instance.hats, array[1], "Hat"); CosmeticResync.Logger.LogInfo((object)$"Loaded {cosmeticIndices.Length} accessories and {cosmeticIndices2.Length} hats"); _currentData.SetValue(MultiCosmetic, new int[2][] { cosmeticIndices, cosmeticIndices2 }); return false; } catch (JsonException) { CosmeticResync.Logger.LogWarning((object)"Failed to deserialize CosmeticResync_MultiCosmetic"); return true; } } internal static void PostfixUpdateCustomPropertiesValue() { if ((Object)(object)MultiCosmetic == (Object)null) { CosmeticResync.Logger.LogError((object)"Missing MultiCosmetic instance? Cannot save MultiCosmetic names"); return; } Customization instance = Singleton<Customization>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { CosmeticResync.Logger.LogError((object)"Customization not initialized? Cannot save MultiCosmetic names"); return; } int[][] array = (int[][])_currentData.GetValue(MultiCosmetic); if (array.Length != 2) { CosmeticResync.Logger.LogError((object)$"Expected MultiCosmetic.Plugin.currentData to contain 2 int[], not {array.Length}"); return; } string[] cosmeticNames = GetCosmeticNames(instance.accessories, array[0], "Accessory"); string[] cosmeticNames2 = GetCosmeticNames(instance.hats, array[1], "Hat"); string text = JsonConvert.SerializeObject((object)new string[2][] { cosmeticNames, cosmeticNames2 }); PlayerPrefs.SetString("CosmeticResync_MultiCosmetic", text); } [HarmonyPostfix] [HarmonyPatch(typeof(PassportManager), "Awake")] internal static void Awake(PassportManager __instance) { Customization component = ((Component)__instance).GetComponent<Customization>(); if (Object.op_Implicit((Object)(object)component)) { Singleton<Customization>._instance = component; CosmeticResync.Logger.LogInfo((object)"Manually updating MultiCosmetic"); PrefixMCDataFromString(); } else { CosmeticResync.Logger.LogError((object)"PassportManager not with Customization? Cannot resync MultiCosmetic"); } } private static int[] GetCosmeticIndices(CustomizationOption[] options, string[] names, string cosmeticType) { Dictionary<string, int> dictionary = new Dictionary<string, int>(0); for (int i = 0; i < options.Length; i++) { CustomizationOption val = options[i]; dictionary[((Object)val).name] = i; } List<int> list = new List<int>(); foreach (string text in names) { if (dictionary.TryGetValue(text, out var value)) { list.Add(value); } else { CosmeticResync.Logger.LogWarning((object)(cosmeticType + " " + text + " is no longer available")); } } return list.ToArray(); } private static string[] GetCosmeticNames(CustomizationOption[] options, int[] indices, string cosmeticType) { List<string> list = new List<string>(); int num = options.Length; foreach (int num2 in indices) { if (num2 >= 0 && num2 < num) { list.Add(((Object)options[num2]).name); } else { CosmeticResync.Logger.LogWarning((object)$"{cosmeticType} #{num2} is out of range"); } } return list.ToArray(); } } }