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 BobasHats v1.1.4
BobaHats.dll
Decompiled 2 weeks agousing 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.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Photon.Pun; using Photon.Realtime; using UnityEngine; using Zorro.Core; using Zorro.Core.Serizalization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BobaHats")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+13bde32de102c984b19d0f35157b9132f071e3c0")] [assembly: AssemblyProduct("BobaHats")] [assembly: AssemblyTitle("BobaHats")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 BobaHats { internal static class BobaHatsPatches { private const int Spacer1 = -1535012113; private const int Spacer2 = 1512782925; private static ManualLogSource Logger => Plugin.Instance.Logger; [HarmonyPatch(typeof(SyncPersistentPlayerDataPackage), "SerializeData")] [HarmonyPostfix] public static void SyncPersistentPlayerDataPackageSerializeData(SyncPersistentPlayerDataPackage __instance, BinarySerializer binarySerializer) { binarySerializer.WriteInt(0); binarySerializer.WriteInt(-1535012113); binarySerializer.WriteInt(1512782925); PersistentPlayerDataService service = GameHandler.GetService<PersistentPlayerDataService>(); if (service == null) { Logger.LogError((object)"PersistentPlayerDataService is null, cannot set hat."); return; } int actorNumber = __instance.ActorNumber; PersistentPlayerData playerData = service.GetPlayerData(actorNumber); Player val = default(Player); if (playerData == null && PhotonNetwork.TryGetPlayer(actorNumber, ref val)) { playerData = service.GetPlayerData(val); } if (playerData == null) { Logger.LogError((object)$"Player data for actor number {actorNumber} is null, cannot set hat."); return; } Customization customizationSingleton = Plugin.GetCustomizationSingleton(); if ((Object)(object)customizationSingleton == (Object)null) { Logger.LogError((object)"Customization component not instantiated yet!"); return; } CustomizationOption[] hats = customizationSingleton.hats; if (hats == null) { Logger.LogError((object)"No hats found in character customization, cannot set hat."); return; } int currentHat = playerData.customizationData.currentHat; if (currentHat < 0 || currentHat >= hats.Length) { Logger.LogWarning((object)$"Invalid hat index {currentHat} for player #{actorNumber}, custom hats may not be loaded yet!"); Plugin.BroadcastPluginEvent("OnLoadHats"); } hats = customizationSingleton.hats; if (currentHat < 0 || currentHat >= hats.Length) { Logger.LogError((object)$"Invalid hat index {currentHat} for player #{actorNumber}, custom hat may be missing!"); return; } CustomizationOption obj = hats[currentHat]; string text = ((obj != null) ? ((Object)obj).name : null) ?? ""; string text2 = JsonConvert.SerializeObject((object)new { hat = text }, (Formatting)0); binarySerializer.WriteString(text2, Encoding.UTF8); Logger.LogDebug((object)$"Serialized hat for player #{actorNumber}: '{text}'"); } [HarmonyPatch(typeof(SyncPersistentPlayerDataPackage), "DeserializeData")] [HarmonyPostfix] public static void SyncPersistentPlayerDataPackageDeserializeData(SyncPersistentPlayerDataPackage __instance, BinaryDeserializer binaryDeserializer) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown if (binaryDeserializer.ReadInt() != 0) { Logger.LogError((object)"Missing 1st spacer trailer in SyncPersistentPlayerDataPackage.DeserializeData."); return; } if (binaryDeserializer.ReadInt() != -1535012113) { Logger.LogError((object)"Missing 1st spacer trailer in SyncPersistentPlayerDataPackage.DeserializeData."); return; } if (binaryDeserializer.ReadInt() != 1512782925) { Logger.LogError((object)"Missing 2nd spacer trailer in SyncPersistentPlayerDataPackage.DeserializeData."); return; } try { using StringReader stringReader = new StringReader(binaryDeserializer.ReadString(Encoding.UTF8)); JsonTextReader val = new JsonTextReader((TextReader)stringReader); try { JObject val2 = (JObject)JToken.ReadFrom((JsonReader)(object)val); string name = ((object)val2["hat"])?.ToString() ?? string.Empty; if (string.IsNullOrEmpty(name)) { Logger.LogError((object)"Hat name is null or empty, cannot set hat."); return; } Logger.LogDebug((object)$"Attempting to deserialize hat for player #{__instance.ActorNumber} to '{name}'"); Customization customizationSingleton = Plugin.GetCustomizationSingleton(); if ((Object)(object)customizationSingleton == (Object)null) { Logger.LogError((object)"Customization component not instantiated yet!"); return; } CustomizationOption[] hats = customizationSingleton.hats; if (hats == null) { Logger.LogError((object)"No hats found in character customization, cannot set hat."); return; } int num = Array.FindIndex(hats, (CustomizationOption hat) => ((Object)hat).name == name); if (num >= 0) { __instance.Data.customizationData.currentHat = num; Logger.LogDebug((object)$"Deserialized hat for player #{__instance.ActorNumber} from '{name}' to #{num}"); } else { Logger.LogError((object)$"Hat '{name}' not found in customization hats, cannot set hat for player #{__instance.ActorNumber}"); } } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception ex) { Logger.LogError((object)$"Failed to deserialize hat for player #{__instance.ActorNumber} from JSON: {ex.Message}\n{ex.StackTrace}"); } } [HarmonyPatch(typeof(PersistentPlayerDataService), "OnSyncReceived")] [HarmonyFinalizer] public static Exception? PersistentPlayerDataServiceOnSyncReceivedFinalizer(PersistentPlayerDataService __instance, SyncPersistentPlayerDataPackage package, Exception? __exception) { if (__exception != null) { Logger.LogWarning((object)("PersistentPlayerDataService.OnSyncReceived threw an exception\n" + __exception.GetType().FullName + ": " + __exception.Message + "\n" + __exception.StackTrace)); } return null; } [HarmonyPatch(typeof(CharacterCustomization), "OnPlayerDataChange")] [HarmonyPostfix] public static void CharacterCustomizationOnPlayerDataChangePostfix(CharacterCustomization __instance, PersistentPlayerData playerData) { Logger.LogDebug((object)$"CharacterCustomization.OnPlayerDataChange called with hat index {playerData.customizationData.currentHat}"); Plugin.BroadcastPluginEvent("OnAddHatsForCharacter", __instance._character); } [HarmonyPatch(typeof(CharacterCustomization), "OnPlayerDataChange")] [HarmonyFinalizer] public static Exception? CharacterCustomizationOnPlayerDataChangeFinalizer(CharacterCustomization __instance, Exception? __exception, PersistentPlayerData playerData) { if (__exception == null) { return null; } Logger.LogWarning((object)("CharacterCustomization.OnPlayerDataChange threw an exception\n" + __exception.GetType().FullName + ": " + __exception.Message + "\n" + __exception.StackTrace)); return null; } [HarmonyPatch(typeof(PersistentPlayerDataService), "OnSyncReceived")] [HarmonyPostfix] public static void PersistentPlayerDataServiceOnSyncReceivedPostfix(PersistentPlayerDataService __instance, SyncPersistentPlayerDataPackage package) { Logger.LogDebug((object)"PersistentPlayerDataService.OnSyncReceived"); } [HarmonyPatch(typeof(PersistentPlayerDataService), "SetPlayerData")] [HarmonyPostfix] public static void PersistentPlayerDataServiceSetPlayerDataPostfix(PersistentPlayerDataService __instance, Player player, PersistentPlayerData playerData) { Logger.LogDebug((object)"PersistentPlayerDataService.SetPlayerData"); } [HarmonyPatch(typeof(PersistentPlayerDataService), "GetPlayerData", new Type[] { typeof(Player) })] [HarmonyPrefix] public static void PersistentPlayerDataServiceGetPlayerDataPrefix(PersistentPlayerDataService __instance, Player player) { Logger.LogDebug((object)"PersistentPlayerDataService.SetPlayerData(Player)"); } [HarmonyPatch(typeof(PersistentPlayerDataService), "GetPlayerData", new Type[] { typeof(int) })] [HarmonyPrefix] public static void PersistentPlayerDataServiceGetPlayerDataPrefix(PersistentPlayerDataService __instance, int actorNumber) { Logger.LogDebug((object)"PersistentPlayerDataService.SetPlayerData(int)"); } [HarmonyPatch(typeof(CharacterCustomization), "OnPlayerDataChange")] [HarmonyPrefix] public static void CharacterCustomizationOnPlayerDataChangePrefix(CharacterCustomization __instance, PersistentPlayerData playerData) { Logger.LogDebug((object)"CharacterCustomization.OnPlayerDataChange(int)"); int currentHat = playerData.customizationData.currentHat; Renderer[] playerHats = __instance.refs.playerHats; if (playerHats != null && playerHats.Length != 0) { for (int i = 0; i < playerHats.Length; i++) { ((Component)playerHats[i]).gameObject.SetActive(i == currentHat); } } } [HarmonyPatch(typeof(CharacterCustomization), "SetCustomizationForRef")] [HarmonyPrefix] public static void CharacterCustomizationSetCustomizationForRefPrefix(CustomizationRefs refs) { Logger.LogDebug((object)"CharacterCustomization.SetCustomizationForRef"); } [HarmonyPatch(typeof(Character), "Awake")] [HarmonyPostfix] public static void CharacterAwakePostfix(Character __instance) { Plugin.BroadcastPluginEvent("OnAddHatsForCharacter", __instance); } [HarmonyPatch(typeof(Character), "Start")] [HarmonyPostfix] public static void CharacterStartPostfix(Character __instance) { Plugin.BroadcastPluginEvent("OnAddHatsForCharacter", __instance); } [HarmonyPatch(typeof(PlayerHandler), "RegisterCharacter")] [HarmonyPostfix] public static void PlayerHandlerRegisterCharacterPostfix(PlayerHandler __instance, Character character) { if ((Object)(object)character == (Object)null) { Logger.LogError((object)"PlayerHandler.RegisterCharacter called with null character, cannot add hats."); return; } Logger.LogDebug((object)$"PlayerHandler.RegisterCharacter called for {character.characterName} ({((MonoBehaviourPun)character).photonView.ViewID})"); Plugin.BroadcastPluginEvent("OnAddHatsForCharacter", character); } [HarmonyPatch(typeof(CharacterCustomization), "Start")] [HarmonyPrefix] public static void CharacterCustomizationStartPrefix(CharacterCustomization __instance) { Logger.LogDebug((object)"CharacterCustomization.Start called"); Plugin.BroadcastPluginEvent("OnLoadHats"); Character character = __instance._character; if (!((Object)(object)character == (Object)null)) { Plugin.BroadcastPluginEvent("OnAddHatsForCharacter", character); } } [HarmonyPatch(typeof(PlayerCustomizationDummy), "UpdateDummy")] [HarmonyPrefix] public static void PlayerCustomizationDummyUpdateDummyPrefix(PlayerCustomizationDummy __instance) { Logger.LogDebug((object)"PlayerCustomizationDummy.UpdateDummy patch called"); FixPlayerCustomizationData(__instance); } private static void FixPlayerCustomizationData(PlayerCustomizationDummy customizationDummy) { try { Plugin.BroadcastPluginEvent("OnLoadHats"); Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter != (Object)null) { Plugin.BroadcastPluginEvent("OnAddHatsForCharacter", localCharacter); } PersistentPlayerDataService service = GameHandler.GetService<PersistentPlayerDataService>(); bool flag = false; Customization customizationSingleton = Plugin.GetCustomizationSingleton(); if ((Object)(object)customizationSingleton != (Object)null) { PersistentPlayerData playerData = service.GetPlayerData(PhotonNetwork.LocalPlayer); CharacterCustomizationData customizationData = playerData.customizationData; if (customizationData.currentSkin < 0 || customizationData.currentSkin > customizationSingleton.skins.Length) { customizationData.currentSkin = 0; flag = true; } if (customizationData.currentOutfit < 0 || customizationData.currentOutfit > customizationSingleton.fits.Length) { customizationData.currentOutfit = 0; flag = true; } if (customizationData.currentHat < 0 || customizationData.currentHat > customizationSingleton.hats.Length) { customizationData.currentHat = 0; flag = true; } if (customizationData.currentEyes < 0 || customizationData.currentEyes > customizationSingleton.eyes.Length) { customizationData.currentEyes = 0; flag = true; } if (customizationData.currentAccessory < 0 || customizationData.currentAccessory > customizationSingleton.accessories.Length) { customizationData.currentAccessory = 0; flag = true; } if (customizationData.currentMouth < 0 || customizationData.currentMouth > customizationSingleton.mouths.Length) { customizationData.currentMouth = 0; flag = true; } if (flag) { service.SetPlayerData(PhotonNetwork.LocalPlayer, playerData); } } } catch (Exception ex) { Logger.LogError((object)("PlayerCustomizationDummy.UpdateDummy patch threw an exception\n" + ex.GetType().FullName + "\n" + ex.Message + "\n" + ex.StackTrace)); } } [HarmonyPatch(typeof(PlayerCustomizationDummy), "UpdateDummy")] [HarmonyFinalizer] public static Exception? PlayerCustomizationDummyUpdateDummyFinalizer(PlayerCustomizationDummy __instance, Exception? __exception) { if (__exception == null) { return null; } if (__exception is IndexOutOfRangeException) { Logger.LogWarning((object)("PlayerCustomizationDummy.UpdateDummy threw an exception\n" + __exception.GetType().FullName + ": " + __exception.Message + "\n" + __exception.StackTrace)); return null; } return __exception; } } [BepInPlugin("BobaHats", "BobaHats", "1.0.0")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <LoadHatsFromBundle>d__14 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Plugin <>4__this; private AssetBundleCreateRequest <createRequest>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadHatsFromBundle>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <createRequest>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Expected O, but got Unknown int num = <>1__state; Plugin plugin = <>4__this; bool flag; switch (num) { default: return false; case 0: { <>1__state = -1; plugin.Logger.LogInfo((object)"Loading hats from bundle."); string text = Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().Location).LocalPath), "bobacustomhats"); if (!File.Exists(text)) { plugin.Logger.LogError((object)("AssetBundle not found at " + text + ". Please ensure the file exists.")); return false; } plugin.Logger.LogDebug((object)("Path to AssetBundle: " + text)); <createRequest>5__2 = AssetBundle.LoadFromFileAsync(text); <>2__current = <createRequest>5__2; <>1__state = 1; return true; } case 1: { <>1__state = -1; AssetBundle assetBundle = <createRequest>5__2.assetBundle; plugin.Logger.LogInfo((object)"AssetBundle loaded."); assetBundle.GetAllAssetNames(); Object[] array = assetBundle.LoadAllAssets(); Object[] array2 = array; foreach (Object val in array2) { plugin.Logger.LogDebug((object)$"Asset: {val.name} ({((object)val).GetType()})"); } plugin.Hats = (from x in array where (x is GameObject || x is Texture2D) ? true : false group x by x.name into x where x.Count() == 2 select new Hat(x.Key, x.OfType<GameObject>().First(), x.OfType<Texture2D>().First())).ToArray(); plugin.HatNames = new HashSet<string>(plugin.Hats.Select((Hat h) => h.Name)); plugin.Logger.LogInfo((object)$"AssetBundle contains {plugin.Hats.Length} hats."); goto IL_021b; } case 2: { <>1__state = -1; if (Application.exitCancellationToken.IsCancellationRequested) { return false; } goto IL_021b; } IL_021b: flag = false; try { plugin.OnLoadHats(); } catch (Exception ex) { plugin.Logger.LogError((object)("Failed to load hats: " + ex.Message + "\n" + ex.StackTrace)); flag = true; } <>2__current = (object)(flag ? new WaitForSecondsRealtime(12f) : new WaitForSecondsRealtime(3f)); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly Lazy<Shader> LazyCharacterShader = new Lazy<Shader>((Func<Shader>)(() => Shader.Find("W/Character"))); [NonSerialized] public Hat[]? Hats; [NonSerialized] public HashSet<string>? HatNames; [NonSerialized] public bool HatsInserted; private const int HatInsertIndex = 23; public static Shader CharacterShader => LazyCharacterShader.Value; internal ManualLogSource Logger => ((BaseUnityPlugin)this).Logger; public static Plugin? Instance { get; private set; } public void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) Instance = this; Logger.LogInfo((object)"Plugin v1.0.0 is starting up."); new Harmony("BobaHats").PatchAll(typeof(BobaHatsPatches)); ((MonoBehaviour)this).StartCoroutine(LoadHatsFromBundle()); } [IteratorStateMachine(typeof(<LoadHatsFromBundle>d__14))] private IEnumerator LoadHatsFromBundle() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadHatsFromBundle>d__14(0) { <>4__this = this }; } internal static Customization? GetCustomizationSingleton() { return Singleton<Customization>.Instance; } internal static Character? GetCharacterByActorNumber(int actorNumber) { return ((IEnumerable<Character>)Character.AllCharacters).FirstOrDefault((Func<Character, bool>)((Character ch) => (Object)(object)((MonoBehaviourPun)ch).photonView != (Object)null && ((MonoBehaviourPun)ch).photonView.Owner != null && ((MonoBehaviourPun)ch).photonView.Owner.ActorNumber == actorNumber)); } internal static Character? GetLocalCharacter() { return Character.localCharacter ?? GetCharacterByActorNumber(PhotonNetwork.LocalPlayer.ActorNumber); } public void OnLoadHats() { Plugin instance = Instance; if ((Object)(object)instance == (Object)null) { Logger.LogError((object)"Plugin instance not loaded yet, cannot instantiate hats!"); return; } if (instance.Hats == null || instance.Hats.Length == 0 || HatNames == null || HatNames.Count == 0) { Logger.LogError((object)"No hats loaded, skipping instantiation!"); return; } Customization customizationSingleton = GetCustomizationSingleton(); if ((Object)(object)customizationSingleton == (Object)null) { Logger.LogError((object)"Customization component not instantiated yet!"); return; } if (customizationSingleton.hats == null || customizationSingleton.hats.Length == 0) { Logger.LogError((object)"CustomizationOptions.hats is not populated yet, not adding hats!"); return; } if (!customizationSingleton.hats.Skip(23).Any((CustomizationOption x) => HatNames.Contains(((Object)x).name))) { Logger.LogDebug((object)"Adding hat CustomizationOptions."); List<CustomizationOption> list = new List<CustomizationOption>(instance.Hats.Length); Hat[] hats = instance.Hats; for (int i = 0; i < hats.Length; i++) { Hat hat = hats[i]; CustomizationOption val = CreateHatOption(hat.Name, hat.Icon); if ((Object)(object)val == (Object)null) { Logger.LogError((object)("Failed to create CustomizationOption for hat '" + hat.Name + "'.")); } else { list.Add(val); } } HatsInserted = true; ArrayInsert(ref customizationSingleton.hats, 23, list); Logger.LogDebug((object)"Completed adding hats to Customization Options."); } PlayerCustomizationDummy dummy = PassportManager.instance.dummy; Transform val2 = TransformExtensions.FindChildRecursive(((Component)dummy).transform, "Hat"); if ((Object)(object)val2 == (Object)null) { Logger.LogError((object)"Dummy hat container not found, cannot instantiate hats for dummy."); return; } if (!HatsInserted) { Logger.LogError((object)"HatsInserted is not set yet, not instantiating hats!"); return; } ref Renderer[] playerHats = ref dummy.refs.playerHats; if (!playerHats.Skip(23).Any((Renderer x) => HatNames.Contains(((Object)x).name))) { Renderer val3 = playerHats.FirstOrDefault(); Renderer obj = playerHats[0]; object obj2; if (obj == null) { obj2 = null; } else { MeshRenderer componentInChildren = ((Component)obj).GetComponentInChildren<MeshRenderer>(true); obj2 = ((componentInChildren != null) ? ((Renderer)componentInChildren).material : null); } Material dummyHatMat = (Material)obj2; Material obj3 = dummyHatMat; Dictionary<string, float> dictionary = ((obj3 != null) ? obj3.GetPropertyNames((MaterialPropertyType)0).ToDictionary((string n) => n, (string n) => dummyHatMat.GetFloat(n)) : null); if ((Object)(object)val3 == (Object)null) { Logger.LogDebug((object)"Dummy is missing hats - something is wrong, aborting..."); return; } int layer = ((Component)val3).gameObject.layer; Logger.LogDebug((object)$"Instantiating hats for dummy as children of {val2}."); List<Renderer> list2 = new List<Renderer>(instance.Hats.Length); Hat[] hats = instance.Hats; for (int i = 0; i < hats.Length; i++) { Hat hat2 = hats[i]; if ((Object)(object)hat2.Prefab == (Object)null) { Logger.LogError((object)("Hat prefab for '" + hat2.Name + "' is null, skipping instantiation for dummy.")); continue; } GameObject val4 = Object.Instantiate<GameObject>(hat2.Prefab, val2); ((Object)val4).name = hat2.Name; GameObjectExtensions.SetLayerRecursivly(val4, layer); MeshRenderer[] componentsInChildren = val4.GetComponentsInChildren<MeshRenderer>(true); for (int j = 0; j < componentsInChildren.Length; j++) { Material material = ((Renderer)componentsInChildren[j]).material; material.enableInstancing = true; ((Object)material).hideFlags = (HideFlags)32; material.shader = CharacterShader; if (dictionary == null) { continue; } foreach (KeyValuePair<string, float> item in dictionary) { material.SetFloat(item.Key, item.Value); } } Renderer componentInChildren2 = val4.GetComponentInChildren<Renderer>(); ((Component)componentInChildren2).gameObject.SetActive(false); list2.Add(componentInChildren2); } ArrayInsert(ref playerHats, 23, list2); Logger.LogDebug((object)"Completed adding hats to Passport dummy."); } Character localCharacter = GetLocalCharacter(); AddHatsForCharacter(localCharacter); if (GameHandler.GetService<PersistentPlayerDataService>() == null) { Logger.LogError((object)"PersistentPlayerDataService is null, cannot set hat."); } } private static void ArrayInsert<T>(ref T[]? array, int insertIndex, IReadOnlyList<T>? toAdd) { if (toAdd == null || toAdd.Count == 0) { return; } if (array == null || array.Length == 0) { array = toAdd.ToArray(); return; } if (insertIndex < 0 || insertIndex > array.Length) { throw new ArgumentOutOfRangeException("insertIndex", $"Insert index ({insertIndex}) is out of bounds."); } T[] array2 = new T[array.Length + toAdd.Count]; if (insertIndex == array.Length) { array.CopyTo(array2, 0); for (int i = 0; i < toAdd.Count; i++) { array2[i + insertIndex] = toAdd[i]; } } else { Array.Copy(array, 0, array2, 0, insertIndex); for (int j = 0; j < toAdd.Count; j++) { array2[j + insertIndex] = toAdd[j]; } int destinationIndex = insertIndex + toAdd.Count; int length = array.Length - insertIndex; Array.Copy(array, insertIndex, array2, destinationIndex, length); } array = array2; } private static void ArrayAppend<T>(ref T[]? array, IReadOnlyList<T>? toAdd) { if (toAdd == null || toAdd.Count == 0) { return; } if (array == null || array.Length == 0) { array = toAdd.ToArray(); return; } T[] array2 = new T[array.Length + toAdd.Count]; array.CopyTo(array2, 0); for (int i = 0; i < toAdd.Count; i++) { array2[i + array.Length] = toAdd[i]; } array = array2; } private void AddHatsForCharacter(Character? character) { Plugin instance = Instance; if ((Object)(object)instance == (Object)null || HatNames == null || instance.Hats == null || instance.Hats.Length == 0) { Logger.LogError((object)"Plugin instance or hats not loaded yet, cannot instantiate hats!"); return; } if (!HatsInserted) { Logger.LogError((object)"HatsInserted is not set yet, not instantiating hats!"); return; } if ((Object)(object)character == (Object)null) { Logger.LogError((object)"Local character not found, cannot instantiate hats!"); return; } CharacterRefs refs = character.refs; if (refs == null) { Logger.LogError((object)$"Character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}' is missing refs!"); return; } CharacterCustomization customization = refs.customization; if ((Object)(object)customization == (Object)null) { Logger.LogError((object)$"Character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}' is missing a customization component!"); return; } ref Renderer[] playerHats = ref customization.refs.playerHats; if (playerHats == null) { Logger.LogError((object)$"Character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}' is missing hats on the customization component!"); return; } if (playerHats.Skip(23).Any((Renderer x) => HatNames.Contains(((Object)x).name))) { Logger.LogDebug((object)$"Character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}' already has hats, skipping."); return; } Logger.LogDebug((object)$"Adding hats to Character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}'"); Transform val = TransformExtensions.FindChildRecursive(((Component)customization).transform, "Hat"); Logger.LogDebug((object)$"Hats container found: {val} (inst #{((Object)val).GetInstanceID()})"); if ((Object)(object)val == (Object)null) { Logger.LogError((object)"Hats container not found, cannot instantiate hats."); return; } Logger.LogDebug((object)$"Instantiating hats as children of {val} (inst #{((Object)val).GetInstanceID()})"); Renderer obj = playerHats[0]; object obj2; if (obj == null) { obj2 = null; } else { MeshRenderer componentInChildren = ((Component)obj).GetComponentInChildren<MeshRenderer>(true); obj2 = ((componentInChildren != null) ? ((Renderer)componentInChildren).material : null); } Material hatMat = (Material)obj2; Material obj3 = hatMat; Dictionary<string, float> dictionary = ((obj3 != null) ? obj3.GetPropertyNames((MaterialPropertyType)0).ToDictionary((string n) => n, (string n) => hatMat.GetFloat(n)) : null); List<Renderer> list = new List<Renderer>(instance.Hats.Length); Hat[] hats = instance.Hats; for (int i = 0; i < hats.Length; i++) { Hat hat = hats[i]; if ((Object)(object)hat.Prefab == (Object)null) { Logger.LogError((object)("Hat prefab for '" + hat.Name + "' is null, skipping instantiation.")); continue; } GameObject val2 = Object.Instantiate<GameObject>(hat.Prefab, val); ((Object)val2).name = hat.Name; MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>(true); for (int j = 0; j < componentsInChildren.Length; j++) { Material material = ((Renderer)componentsInChildren[j]).material; material.enableInstancing = true; ((Object)material).hideFlags = (HideFlags)32; material.shader = CharacterShader; if (dictionary == null) { continue; } foreach (KeyValuePair<string, float> item in dictionary) { material.SetFloat(item.Key, item.Value); } } Renderer componentInChildren2 = val2.GetComponentInChildren<Renderer>(); ((Component)componentInChildren2).gameObject.SetActive(false); list.Add(componentInChildren2); } ArrayInsert(ref playerHats, 23, list); Logger.LogDebug((object)$"Completed adding hats to Character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}'"); } public static CustomizationOption CreateHatOption(string hatName, Texture2D icon) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) CustomizationOption obj = ScriptableObject.CreateInstance<CustomizationOption>(); obj.color = Color.white; ((Object)obj).name = hatName; obj.texture = (Texture)(object)icon; obj.type = (Type)50; obj.requiredAchievement = (ACHIEVEMENTTYPE)0; return obj; } public static void OnAddHatsForCharacter(Character character) { if ((Object)(object)character == (Object)null) { Plugin? instance = Instance; if (instance != null) { instance.Logger.LogError((object)"OnAddHatsForCharacter called for null character."); } return; } Plugin? instance2 = Instance; if (instance2 != null) { instance2.Logger.LogDebug((object)$"OnAddHatsForCharacter called for character #{((MonoBehaviourPun)character).photonView.Owner.ActorNumber} '{((Object)character).name}'"); } Instance?.AddHatsForCharacter(character); } public static void BroadcastPluginEvent(string message) { Plugin instance = Instance; BaseUnityPlugin[] array = Resources.FindObjectsOfTypeAll<BaseUnityPlugin>(); foreach (BaseUnityPlugin val in array) { Type type = ((object)val).GetType(); MethodInfo method = type.GetMethod(message, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Any, Array.Empty<Type>(), null); if (!(method == null)) { if (instance != null) { instance.Logger.LogDebug((object)("Calling " + method.Name + " on plugin " + type.FullName)); } method.Invoke(method.IsStatic ? null : val, Array.Empty<object>()); } } } public static void BroadcastPluginEvent(string message, params object[] args) { string message2 = message; object[] args2 = args; if (args2 == null) { throw new ArgumentNullException("args"); } Plugin instance = Instance; BaseUnityPlugin[] array = Resources.FindObjectsOfTypeAll<BaseUnityPlugin>(); foreach (BaseUnityPlugin val in array) { Type type = ((object)val).GetType(); MethodInfo methodInfo = (MethodInfo)type.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MemberInfo m) => m.Name == message2 && m is MethodInfo mi && HasCompatibleParameters(mi, args2)); if (!(methodInfo == null)) { if (instance != null) { instance.Logger.LogDebug((object)("Calling " + methodInfo.Name + " on plugin " + type.FullName)); } methodInfo.Invoke(methodInfo.IsStatic ? null : val, args2); } } } private static bool HasCompatibleParameters(MethodInfo mi, object[] args) { ParameterInfo[] parameters = mi.GetParameters(); if (parameters.Length != args.Length) { return false; } for (int i = 0; i < args.Length; i++) { if (!IsCompatibleParameter(parameters[i].ParameterType, args[i])) { return false; } } return true; } private static bool IsCompatibleParameter(Type paramType, object? arg) { if (arg == null) { if (paramType.IsValueType) { return Nullable.GetUnderlyingType(paramType) != null; } return true; } if (!paramType.IsInstanceOfType(arg)) { if (paramType.IsGenericType && paramType.GetGenericTypeDefinition() == typeof(Nullable<>)) { return Nullable.GetUnderlyingType(paramType).IsInstanceOfType(arg); } return false; } return true; } } public struct Hat { public string Name; public GameObject Prefab; public Texture2D Icon; public Hat(string name, GameObject prefab, Texture2D icon) { Name = name; Prefab = prefab; Icon = icon; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "BobaHats"; public const string PLUGIN_NAME = "BobaHats"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }