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