Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ExtraCompany v1.0.0
plugins/ExtraCompany/aj.ExtraHeads.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DunGen; using ExtraHeads.Configuration; using ExtraHeads.Cosmetics; using ExtraHeads.UI; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks; using Steamworks.Data; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [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("aj.ExtraHeads")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ExtraCompany")] [assembly: AssemblyTitle("aj.ExtraHeads")] [assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was created with the assistance of generative AI (code); see the README credits for which assets.")] [assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")] [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.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] [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] [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 ExtraHeads { [HarmonyPatch] internal static class GameFixes { [HarmonyPatch(typeof(StartOfRound), "OnClientConnect")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FreeSlotSearch(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "OnClientConnect", 1, Il.LoopTo4, Il.Slots); } [HarmonyPatch(typeof(StartOfRound), "SyncShipUnlockablesServerRpc")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SuitsServer(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "SyncShipUnlockablesServerRpc", 2, (List<CodeInstruction> c, int i) => Il.NewArrayOf4(c, i) || Il.LoopTo4(c, i), Il.Slots); } [HarmonyPatch(typeof(StartOfRound), "SyncShipUnlockablesClientRpc")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SuitsClient(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "SyncShipUnlockablesClientRpc", 1, Il.LoopTo4, Il.Slots); } [HarmonyPatch(typeof(HUDManager), "SyncAllPlayerLevelsServerRpc", new Type[] { })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Levels(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "SyncAllPlayerLevelsServerRpc", 2, Il.NewArrayOf4, Il.Slots); } [HarmonyPatch(typeof(PlayerControllerB), "SendNewPlayerValuesServerRpc")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Names(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "SendNewPlayerValuesServerRpc", 1, Il.LoopTo4, Il.Slots); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> CameraCheck(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "PlayerControllerB.Update", 1, (List<CodeInstruction> c, int i) => Il.IsConst(c[i], 4) && i > 0 && Il.LoadsLocal(c[i - 1]) && i + 1 < c.Count && (c[i + 1].opcode == OpCodes.Bne_Un || c[i + 1].opcode == OpCodes.Bne_Un_S), Il.Slots); } [HarmonyPatch(typeof(EnemyAI), "TargetClosestPlayer")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> TargetEverySlot(IEnumerable<CodeInstruction> code) { return LoopOverGaps(code, "TargetClosestPlayer"); } [HarmonyPatch(typeof(RoundManager), "AverageOfLivingGroupedPlayerPositions")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> AverageEverySlot(IEnumerable<CodeInstruction> code) { return LoopOverGaps(code, "AverageOfLivingGroupedPlayerPositions"); } private static IEnumerable<CodeInstruction> LoopOverGaps(IEnumerable<CodeInstruction> code, string where) { Label? label = default(Label?); return Il.Swap(code, where, 1, (List<CodeInstruction> c, int i) => c[i].opcode == OpCodes.Add && i >= 2 && Il.IsConst(c[i - 1], 1) && Il.Loads(c[i - 2], "connectedPlayersAmount") && i + 1 < c.Count && CodeInstructionExtensions.Branches(c[i + 1], ref label), () => (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Add, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LobbySize), "LoopEnd", (Type[])null, (Type[])null)) }); } [HarmonyPatch(typeof(QuickMenuManager), "AddUserToPlayerList")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ListRows(IEnumerable<CodeInstruction> code) { Label? label = default(Label?); return Il.Swap(code, "AddUserToPlayerList", 1, (List<CodeInstruction> c, int i) => Il.IsConst(c[i], 4) && i + 1 < c.Count && CodeInstructionExtensions.Branches(c[i + 1], ref label), () => (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(GameFixes), "LastListRow", (Type[])null, (Type[])null)) }); } public static int LastListRow(QuickMenuManager menu) { return menu.playerListSlots.Length - 1; } [HarmonyPatch(typeof(QuickMenuManager), "RemoveUserFromPlayerList")] [HarmonyPrefix] private static bool OnlyListedRows(QuickMenuManager __instance, int playerObjectId) { if (playerObjectId >= 0) { return playerObjectId < __instance.playerListSlots.Length; } return false; } [HarmonyPatch(typeof(QuickMenuManager), "ConfirmKickUserFromServer")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> KickAnyone(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "ConfirmKickUserFromServer", 1, (List<CodeInstruction> c, int i) => Il.IsConst(c[i], 3) && i > 0 && Il.Loads(c[i - 1], "playerObjToKick"), Il.LastSlot); } [HarmonyPatch(typeof(HUDManager), "AddChatMessage")] [HarmonyPrefix] private static void NameEveryone(ref string chatMessage) { if (LobbySize.Expanded && !string.IsNullOrEmpty(chatMessage) && chatMessage.Contains("[playerNum")) { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; StringBuilder stringBuilder = new StringBuilder(chatMessage); for (int i = 4; i < allPlayerScripts.Length; i++) { stringBuilder.Replace($"[playerNum{i}]", allPlayerScripts[i].playerUsername); } chatMessage = stringBuilder.ToString(); } } [HarmonyPatch(typeof(HUDManager), "FillEndGameStats")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ResultsRows(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "FillEndGameStats", 1, (List<CodeInstruction> c, int i) => c[i].opcode == OpCodes.Ldlen && i > 0 && Il.Loads(c[i - 1], "allPlayerScripts"), () => (CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldlen, (object)null), new CodeInstruction(OpCodes.Conv_I4, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(GameFixes), "ShownResults", (Type[])null, (Type[])null)) }); } public static int ShownResults(int players) { return Mathf.Min(players, HUDManager.Instance.statsUIElements.playerNamesText.Length); } } [HarmonyPatch] internal static class IdleSlots { private static readonly Dictionary<PlayerControllerB, List<Behaviour>> parked = new Dictionary<PlayerControllerB, List<Behaviour>>(); private static readonly FieldRef<PlayerControllerB, bool> CameraDisabled = AccessTools.FieldRefAccess<PlayerControllerB, bool>("isCameraDisabled"); private static bool Empty(PlayerControllerB player) { if (!player.isPlayerControlled) { return !player.isPlayerDead; } return false; } [HarmonyPatch(typeof(StartOfRound), "Update")] [HarmonyPostfix] private static void ParkEmptySlots(StartOfRound __instance) { if (!LobbySize.Expanded || __instance.allPlayerScripts == null) { return; } PlayerControllerB[] allPlayerScripts = __instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val == (Object)null) { continue; } if (Empty(val) && CameraDisabled.Invoke(val)) { if (!parked.ContainsKey(val)) { parked[val] = SwitchOffScripts(val); } Switch(val, on: false); } else { if (!parked.TryGetValue(val, out List<Behaviour> value)) { continue; } parked.Remove(val); Switch(val, on: true); foreach (Behaviour item in value) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } } } } private static List<Behaviour> SwitchOffScripts(PlayerControllerB player) { List<Behaviour> list = new List<Behaviour>(); Behaviour[] componentsInChildren = ((Component)player).GetComponentsInChildren<Behaviour>(); foreach (Behaviour val in componentsInChildren) { if (val.enabled && !(val is NetworkBehaviour) && !(val is NetworkObject) && !(val is Camera) && !(val is AudioListener)) { val.enabled = false; list.Add(val); } } return list; } private static void Switch(PlayerControllerB player, bool on) { if ((Object)(object)player.thisController != (Object)null && ((Collider)player.thisController).enabled != on) { ((Collider)player.thisController).enabled = on; } Switch((Renderer?)(object)player.thisPlayerModel, on); Switch((Renderer?)(object)player.thisPlayerModelLOD1, on); Switch((Renderer?)(object)player.thisPlayerModelLOD2, on); } private static void Switch(Renderer? body, bool on) { if ((Object)(object)body != (Object)null && body.enabled != on) { body.enabled = on; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPrefix] private static bool RunUnlessEmpty(PlayerControllerB __instance) { if (LobbySize.Expanded && Empty(__instance)) { return !CameraDisabled.Invoke(__instance); } return true; } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void Forget() { parked.Clear(); } } internal static class Il { internal static IEnumerable<CodeInstruction> Swap(IEnumerable<CodeInstruction> instructions, string where, int expected, Func<List<CodeInstruction>, int, bool> isPlayerCount, Func<CodeInstruction[]> replacement) { List<CodeInstruction> list = instructions.ToList(); List<int> list2 = new List<int>(); for (int i = 0; i < list.Count; i++) { if (isPlayerCount(list, i)) { list2.Add(i); } } if (list2.Count != expected) { Plugin.Logger.LogWarning((object)$"{where}: expected {expected} player count(s), found {list2.Count}; left unchanged (game update?)."); return list; } for (int num = list2.Count - 1; num >= 0; num--) { int index = list2[num]; CodeInstruction[] array = replacement(); array[0].labels.AddRange(list[index].labels); array[0].blocks.AddRange(list[index].blocks); list.RemoveAt(index); list.InsertRange(index, array); } return list; } internal static bool IsConst(CodeInstruction ci, int value) { return CodeInstructionExtensions.LoadsConstant(ci, (long)value); } internal static bool Loads(CodeInstruction ci, string field) { if ((ci.opcode == OpCodes.Ldfld || ci.opcode == OpCodes.Ldsfld) && ci.operand is FieldInfo fieldInfo) { return fieldInfo.Name == field; } return false; } internal static bool Calls(CodeInstruction ci, string method) { if ((ci.opcode == OpCodes.Call || ci.opcode == OpCodes.Callvirt) && ci.operand is MethodBase methodBase) { return methodBase.Name == method; } return false; } internal static bool LoadsLocal(CodeInstruction ci) { return ci.opcode.Name.StartsWith("ldloc"); } internal static bool NewArrayOf4(List<CodeInstruction> c, int i) { if (IsConst(c[i], 4) && i + 1 < c.Count) { return c[i + 1].opcode == OpCodes.Newarr; } return false; } internal static bool LoopTo4(List<CodeInstruction> c, int i) { Label? label = default(Label?); if (IsConst(c[i], 4) && i > 0 && LoadsLocal(c[i - 1]) && i + 1 < c.Count) { return CodeInstructionExtensions.Branches(c[i + 1], ref label); } return false; } internal static CodeInstruction[] Slots() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown return (CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(LobbySize), "Slots")) }; } internal static CodeInstruction[] LastSlot() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown return (CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(LobbySize), "LastSlot")) }; } } [HarmonyPatch] internal static class Joining { internal const string LobbyKey = "extraheads"; private const string PayloadTag = "ExtraHeads"; private const string SizeReason = "EXTRAHEADS_SIZE:"; private const float LanRetryDelay = 1f; private static bool retryAtHostSize; [HarmonyPatch(typeof(GameNetworkManager), "StartHost")] [HarmonyPrefix] private static void HostAtConfigSize() { LobbySize.Set(Plugin.BoundConfig.LobbySize.Value, "hosting"); GameNetworkManager.Instance.maxAllowedPlayers = LobbySize.Limit; } [HarmonyPatch(typeof(SteamMatchmaking), "CreateLobbyAsync")] [HarmonyPrefix] private static void LobbyRoom(ref int maxMembers) { maxMembers = LobbySize.Limit; } [HarmonyPatch(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyCreated")] [HarmonyPostfix] private static void MarkLobby(Lobby lobby) { ((Lobby)(ref lobby)).SetData("extraheads", "1.0.0"); } [HarmonyPatch(typeof(GameNetworkManager), "LobbyDataIsJoinable")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FullAtLobbyRoom(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "LobbyDataIsJoinable", 1, (List<CodeInstruction> c, int i) => Il.IsConst(c[i], 4) && i > 0 && Il.Calls(c[i - 1], "get_MemberCount"), () => (CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LobbySize), "RoomOf", (Type[])null, (Type[])null)) }); } [HarmonyPatch(typeof(GameNetworkManager), "LobbyDataIsJoinable")] [HarmonyPostfix] private static void TakeLobbySize(Lobby lobby, ref bool __result) { if (!__result) { return; } string data = ((Lobby)(ref lobby)).GetData("extraheads"); if (string.IsNullOrEmpty(data)) { if (((Lobby)(ref lobby)).MaxMembers > 4) { __result = Refuse("This lobby uses a different player-count mod, not Extra Heads."); } else { LobbySize.Set(4, "joining a normal lobby"); } } else if (data != "1.0.0") { __result = Refuse("The host has Extra Heads " + data + "; you have 1.0.0."); } else { LobbySize.Set(((Lobby)(ref lobby)).MaxMembers, "joining a Steam lobby"); } } private static bool Refuse(string why) { MenuManager obj = Object.FindObjectOfType<MenuManager>(); if (obj != null) { obj.SetLoadingScreen(false, (RoomEnter)5, why); } return false; } [HarmonyPatch(typeof(GameNetworkManager), "SetConnectionDataBeforeConnecting")] [HarmonyPostfix] private static void TagConnectionData() { NetworkConfig networkConfig = NetworkManager.Singleton.NetworkConfig; string s = Encoding.ASCII.GetString(networkConfig.ConnectionData) + string.Format(",{0}:{1}:{2}", "ExtraHeads", "1.0.0", LobbySize.Slots); networkConfig.ConnectionData = Encoding.ASCII.GetBytes(s); } [HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FullAtLimit(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "ConnectionApproval", 1, (List<CodeInstruction> c, int i) => Il.IsConst(c[i], 4) && i > 0 && Il.Loads(c[i - 1], "connectedPlayers"), () => (CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(LobbySize), "Limit")) }); } [HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")] [HarmonyPostfix] [HarmonyBefore(new string[] { "LateLanding" })] private static void CheckJoiner(ConnectionApprovalRequest request, ConnectionApprovalResponse response) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (response.Approved && request.ClientNetworkId != NetworkManager.Singleton.LocalClientId) { string text = JoinerProblem(Encoding.ASCII.GetString(request.Payload)); if (text != null) { response.Approved = false; response.Reason = text; Plugin.Logger.LogInfo((object)$"Refused joiner {request.ClientNetworkId}: {text}"); } } } private static string? JoinerProblem(string payload) { string text = payload.Split(',').FirstOrDefault((string part) => part.StartsWith("ExtraHeads:")); if (text == null) { if (!LobbySize.Expanded) { return null; } return $"This lobby holds {LobbySize.Limit} players and needs the Extra Heads mod."; } string[] array = text.Split(':'); string text2 = ((array.Length > 1) ? array[1] : "?"); if (text2 != "1.0.0") { return "ExtraCompany version mismatch: the host has 1.0.0, you have " + text2 + "."; } if (array.Length < 3 || !int.TryParse(array[2], out var result) || result != LobbySize.Slots) { return "EXTRAHEADS_SIZE:" + LobbySize.Slots; } return null; } [HarmonyPatch(typeof(GameNetworkManager), "OnLocalClientConnectionDisapproved")] [HarmonyPrefix] private static void ReadSizeRefusal() { NetworkManager singleton = NetworkManager.Singleton; string text = ((singleton != null) ? singleton.DisconnectReason : null); if (text != null && text.StartsWith("EXTRAHEADS_SIZE:") && int.TryParse(text.Substring("EXTRAHEADS_SIZE:".Length), out var result)) { LobbySize.Set(result, "the host's lobby size"); retryAtHostSize = true; } } [HarmonyPatch(typeof(GameNetworkManager), "OnLocalClientConnectionDisapproved")] [HarmonyPostfix] private static void RetryAtHostSize(GameNetworkManager __instance) { if (!retryAtHostSize) { return; } retryAtHostSize = false; __instance.disconnectionReasonMessage = ""; if (__instance.disableSteam) { ((MonoBehaviour)__instance).StartCoroutine(JoinLanAgain()); return; } MenuManager obj = Object.FindObjectOfType<MenuManager>(); if (obj != null) { obj.SetLoadingScreen(false, (RoomEnter)5, $"The lobby now holds {LobbySize.Slots} players. Join again."); } } private static IEnumerator JoinLanAgain() { yield return (object)new WaitForSeconds(1f); MenuManager val = Object.FindObjectOfType<MenuManager>(); if ((Object)(object)val != (Object)null) { Plugin.Logger.LogInfo((object)$"Joining the LAN host again at its lobby size ({LobbySize.Slots})."); val.StartAClient(); } } } [HarmonyPatch] internal static class LoadingSpeed { private const float FrameBudgetMs = 40f; private static readonly Stopwatch building = new Stopwatch(); private static int frames; [HarmonyPatch(typeof(RoundManager), "GenerateNewFloor")] [HarmonyPrefix] private static void BuildFaster(RoundManager __instance) { DungeonGenerator val = __instance.dungeonGenerator?.Generator; if (val != null) { if (Plugin.BoundConfig.FastLoading.Value && val.GenerateAsynchronously) { val.MaxAsyncFrameMilliseconds = 40f; } frames = Time.frameCount; building.Restart(); } } [HarmonyPatch(typeof(RoundManager), "FinishGeneratingLevel")] [HarmonyPostfix] private static void Built() { if (building.IsRunning) { building.Stop(); Plugin.Logger.LogInfo((object)($"Facility built in {building.Elapsed.TotalSeconds:0.00} s over {Time.frameCount - frames} frames " + "(fast loading " + (Plugin.BoundConfig.FastLoading.Value ? "on" : "off") + ").")); } } } internal static class LobbySize { internal const int Vanilla = 4; internal const int Ceiling = 16; internal const int Smallest = 1; public static int Limit { get; private set; } = 4; public static int Slots { get; private set; } = 4; public static int LastSlot => Slots - 1; internal static bool Expanded => Slots > 4; public static int AllSeenShortcut { get { if (!Expanded) { return 4; } return -1; } } internal static void Set(int size, string why) { int num = Mathf.Clamp(size, 1, 16); int num2 = Mathf.Clamp(size, 4, 16); if (num != Limit || num2 != Slots) { Plugin.Logger.LogInfo((object)$"Lobby size {Limit} -> {num}, player slots {Slots} -> {num2} ({why})."); } Limit = num; Slots = num2; } public static int RoomOf(Lobby lobby) { if (!string.IsNullOrEmpty(((Lobby)(ref lobby)).GetData("extraheads"))) { return Mathf.Clamp(((Lobby)(ref lobby)).MaxMembers, 1, 16); } return 4; } public static int LoopEnd(int vanillaEnd) { if (!Expanded) { return vanillaEnd; } return Slots; } } [HarmonyPatch] internal static class MonsterFixes { [HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ClosestOfAll(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "EnemyAI.GetClosestPlayer", 1, Il.LoopTo4, Il.Slots); } [HarmonyPatch(typeof(EnemyAI), "GetAllPlayersInLineOfSight")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SeenAreSeen(IEnumerable<CodeInstruction> code) { return NoAllSeenShortcut(code, "EnemyAI.GetAllPlayersInLineOfSight"); } [HarmonyPatch(typeof(CaveDwellerAI), "GetAllPlayerBodiesInLineOfSight")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ManeaterSeenAreSeen(IEnumerable<CodeInstruction> code) { return NoAllSeenShortcut(code, "CaveDwellerAI.GetAllPlayerBodiesInLineOfSight"); } private static IEnumerable<CodeInstruction> NoAllSeenShortcut(IEnumerable<CodeInstruction> code, string where) { return Il.Swap(code, where, 1, (List<CodeInstruction> c, int i) => Il.IsConst(c[i], 4) && i > 0 && Il.Calls(c[i - 1], "get_Count"), () => (CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(LobbySize), "AllSeenShortcut")) }); } [HarmonyPatch(typeof(BushWolfEnemy), "GetClosestPlayerToNest")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FoxNest(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "BushWolfEnemy.GetClosestPlayerToNest", 1, Il.LoopTo4, Il.Slots); } [HarmonyPatch(typeof(SpringManAI), "Update")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> CoilHeadWatchers(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "SpringManAI.Update", 1, Il.LoopTo4, Il.Slots); } [HarmonyPatch(typeof(DressGirlAI), "ChoosePlayerToHaunt")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GhostGirlChoice(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "DressGirlAI.ChoosePlayerToHaunt", 3, (List<CodeInstruction> c, int i) => Il.LoopTo4(c, i) || Il.NewArrayOf4(c, i), Il.Slots); } [HarmonyPatch(typeof(ForestGiantAI), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GiantStealth(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "ForestGiantAI.Start", 1, Il.NewArrayOf4, Il.Slots); } [HarmonyPatch(typeof(ButlerEnemyAI), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ButlerMemory(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "ButlerEnemyAI.Start", 3, Il.NewArrayOf4, Il.Slots); } [HarmonyPatch(typeof(BlobAI), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> HygrodereBodies(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "BlobAI.Start", 1, Il.NewArrayOf4, Il.Slots); } [HarmonyPatch(typeof(CrawlerAI), "Start")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ThumperReach(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "CrawlerAI.Start", 1, Il.NewArrayOf4, Il.Slots); } [HarmonyPatch(typeof(ShipTeleporter), "Awake")] [HarmonyPostfix] private static void TeleportAnyone(ref int[] ___playersBeingTeleported) { int num = ___playersBeingTeleported.Length; if (num < LobbySize.Slots) { Array.Resize(ref ___playersBeingTeleported, LobbySize.Slots); for (int i = num; i < LobbySize.Slots; i++) { ___playersBeingTeleported[i] = -1; } } } } [HarmonyPatch] internal static class OtherExpanders { private static bool done; internal static bool Found { get; private set; } [HarmonyPatch(typeof(MenuManager), "Start")] [HarmonyPrefix] [HarmonyPriority(800)] private static void StepAsideIfAnother() { if (!done) { done = true; MethodInfo methodInfo = AccessTools.Method(typeof(NetworkSceneManager), "PopulateScenePlacedObjects", (Type[])null, (Type[])null); Patches val = ((methodInfo != null) ? Harmony.GetPatchInfo((MethodBase)methodInfo) : null); HashSet<string> hashSet = ((val != null) ? new HashSet<string>(val.Owners) : new HashSet<string>()); hashSet.Remove("ExtraCompany"); if (hashSet.Count != 0) { Found = true; Plugin.Logger.LogError((object)("Another mod also adds player slots (" + string.Join(", ", hashSet) + "): Extra Heads stays off. Remove one of the two; they can't run together.")); Plugin.Harmony.UnpatchSelf(); } } } } [HarmonyPatch] internal static class PlayerSlots { private const uint HashBase = 1162346496u; private const uint HashStride = 32u; private const float SpawnSpacing = 0.7f; private static readonly FieldRef<NetworkObject, uint> GlobalHash = AccessTools.FieldRefAccess<NetworkObject, uint>("GlobalObjectIdHash"); private static readonly FieldRef<PlayerControllerB, Collider[]> NearByPlayers = AccessTools.FieldRefAccess<PlayerControllerB, Collider[]>("nearByPlayers"); [HarmonyPatch(typeof(NetworkSceneManager), "PopulateScenePlacedObjects")] [HarmonyPostfix] private static void AddExtraPlayers(Dictionary<uint, Dictionary<int, NetworkObject>> ___ScenePlacedObjects) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Expected O, but got Unknown StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.allPlayerObjects.Length >= LobbySize.Slots) { return; } int num = instance.allPlayerObjects.Length; int slots = LobbySize.Slots; GameObject val = instance.allPlayerObjects[num - 1]; Array.Resize(ref instance.allPlayerObjects, slots); Array.Resize(ref instance.allPlayerScripts, slots); Array.Resize(ref instance.gameStats.allPlayerStats, slots); Array.Resize(ref instance.playerSpawnPositions, slots); for (int i = num; i < slots; i++) { GameObject val2 = Object.Instantiate<GameObject>(val, val.transform.parent); ((Object)val2).name = $"Player ({i})"; NetworkObject[] componentsInChildren = val2.GetComponentsInChildren<NetworkObject>(true); for (int j = 0; j < componentsInChildren.Length; j++) { uint num2 = (uint)(1162346496 + i * 32 + j); GlobalHash.Invoke(componentsInChildren[j]) = num2; Scene scene = ((Component)componentsInChildren[j]).gameObject.scene; int handle = ((Scene)(ref scene)).handle; if (!___ScenePlacedObjects.TryGetValue(num2, out Dictionary<int, NetworkObject> value)) { value = (___ScenePlacedObjects[num2] = new Dictionary<int, NetworkObject>()); } value[handle] = componentsInChildren[j]; } PlayerControllerB componentInChildren = val2.GetComponentInChildren<PlayerControllerB>(); componentInChildren.playerClientId = (ulong)i; componentInChildren.playerUsername = $"Player #{i}"; componentInChildren.isPlayerControlled = false; componentInChildren.isPlayerDead = false; componentInChildren.TeleportPlayer(instance.notSpawnedPosition.position, false, 0f, false, true); instance.allPlayerObjects[i] = val2; instance.allPlayerScripts[i] = componentInChildren; instance.gameStats.allPlayerStats[i] = new PlayerStats(); instance.playerSpawnPositions[i] = ExtraSpawnSpot(instance, i); instance.mapScreen.radarTargets.Add(new TransformAndName(((Component)componentInChildren).transform, componentInChildren.playerUsername, false)); } Plugin.Logger.LogInfo((object)$"Player slots {num} -> {slots}."); } private static Transform ExtraSpawnSpot(StartOfRound round, int slot) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Transform val = round.playerSpawnPositions[slot % 4]; int num = (slot - 4) / 4; float num2 = ((num % 2 == 0) ? 1f : (-1f)) * 0.7f * (float)(num / 2 + 1); Vector3 val2 = val.position + val.right * num2; Bounds bounds = round.shipInnerRoomBounds.bounds; Vector3 val3 = ((Bounds)(ref bounds)).ClosestPoint(val2); Transform transform = new GameObject($"ExtraHeads spawn {slot}").transform; transform.SetParent(val.parent, true); transform.SetPositionAndRotation(new Vector3(val3.x, val.position.y, val3.z), val.rotation); return transform; } [HarmonyPatch(typeof(PlayerControllerB), "Start")] [HarmonyPostfix] private static void RoomForEveryone(PlayerControllerB __instance) { if (LobbySize.Expanded) { NearByPlayers.Invoke(__instance) = (Collider[])(object)new Collider[LobbySize.Slots]; } } [HarmonyPatch(typeof(PlayerControllerB), "NearOtherPlayers")] [HarmonyPrefix] private static bool SkipEmptySlots(PlayerControllerB __instance, float checkRadius, ref bool __result) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!LobbySize.Expanded) { return true; } __result = false; PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return false; } float num = checkRadius * checkRadius; PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)__instance && val.isPlayerControlled) { Vector3 val2 = ((Component)__instance).transform.position - ((Component)val).transform.position; if (((Vector3)(ref val2)).sqrMagnitude < num) { __result = true; break; } } } return false; } [HarmonyPatch(typeof(StartOfRound), "GetPlayerSpawnPosition")] [HarmonyFinalizer] private static Exception? SpawnFallback(Exception? __exception, StartOfRound __instance, ref Vector3 __result) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (__exception is IndexOutOfRangeException && LobbySize.Expanded) { __result = __instance.playerSpawnPositions[0].position + Vector3.up * 0.5f; return null; } return __exception; } } [BepInPlugin("ExtraCompany", "ExtraCompany", "1.0.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; internal static PluginConfig BoundConfig { get; private set; } internal static Harmony Harmony { get; private set; } private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; BoundConfig = new PluginConfig(((BaseUnityPlugin)this).Config); Harmony = new Harmony("ExtraCompany"); Harmony.PatchAll(typeof(OtherExpanders)); Harmony.PatchAll(typeof(Joining)); Harmony.PatchAll(typeof(PlayerSlots)); Harmony.PatchAll(typeof(IdleSlots)); Harmony.PatchAll(typeof(GameFixes)); Harmony.PatchAll(typeof(Voice)); Harmony.PatchAll(typeof(MonsterFixes)); Harmony.PatchAll(typeof(LoadingSpeed)); Harmony.PatchAll(typeof(LobbyPicker)); Harmony.PatchAll(typeof(PlayerList)); Harmony.PatchAll(typeof(ResultsGrid)); Harmony.PatchAll(typeof(SpectatorList)); Harmony.PatchAll(typeof(Wardrobe)); Harmony.PatchAll(typeof(CosmeticPicker)); Logger.LogInfo((object)"Plugin ExtraCompany is loaded!"); } } [HarmonyPatch] internal static class Voice { private const float PitchLerpSpeed = 3f; private const float NeutralPitch = 1f; private const float StartVolume = 0.5f; [HarmonyPatch(typeof(SoundManager), "Start")] [HarmonyPostfix] private static void VoiceForEveryone(SoundManager __instance) { if (LobbySize.Expanded) { int slots = LobbySize.Slots; Grow(ref __instance.playerVoicePitchLerpSpeed, slots, 3f); Grow(ref __instance.playerVoicePitchTargets, slots, 1f); Grow(ref __instance.playerVoicePitches, slots, 1f); Grow(ref __instance.playerVoiceVolumes, slots, 0.5f); AudioMixerGroup[] playerVoiceMixers = __instance.playerVoiceMixers; int num = playerVoiceMixers.Length; Array.Resize(ref __instance.playerVoiceMixers, slots); for (int i = num; i < slots; i++) { __instance.playerVoiceMixers[i] = playerVoiceMixers[i % num]; } } } private static void Grow(ref float[] values, int slots, float fill) { int num = values.Length; if (num < slots) { Array.Resize(ref values, slots); for (int i = num; i < slots; i++) { values[i] = fill; } } } [HarmonyPatch(typeof(SoundManager), "SetPlayerVoiceFilters")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> OnlyRealChannels(IEnumerable<CodeInstruction> code) { return Il.Swap(code, "SetPlayerVoiceFilters", 2, (List<CodeInstruction> c, int i) => c[i].opcode == OpCodes.Ldlen && i > 0 && Il.Loads(c[i - 1], "allPlayerScripts"), () => (CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldlen, (object)null), new CodeInstruction(OpCodes.Conv_I4, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Voice), "MixerChannels", (Type[])null, (Type[])null)) }); } public static int MixerChannels(int players) { return Mathf.Min(players, 4); } [HarmonyPatch(typeof(SoundManager), "SetPlayerPitch")] [HarmonyPrefix] private static bool OnlyRealPitch(int playerObjNum) { return playerObjNum < 4; } } public static class PluginInfo { public const string PLUGIN_GUID = "ExtraCompany"; public const string PLUGIN_NAME = "ExtraCompany"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace ExtraHeads.UI { [HarmonyPatch] internal static class CosmeticPicker { [CompilerGenerated] private static class <>O { public static UnityAction <0>__Close; } private const float CellShare = 0.15f; private const float PadShare = 0.025f; private const float HeaderShare = 0.11f; private const float FooterShare = 0.09f; private const int Columns = 5; private const float NameSize = 0.024f; private const float TitleSize = 0.05f; private const float HintSize = 0.026f; private const float ButtonTextSize = 0.032f; private static readonly Color Backdrop = new Color(0f, 0f, 0f, 0.6f); private static readonly Color Panel = new Color(0.12f, 0.02f, 0.01f, 0.97f); private static readonly Color Cell = new Color(0.22f, 0.05f, 0.03f, 1f); private static readonly Color CellWorn = new Color(0.55f, 0.2f, 0.05f, 1f); private static readonly Color Orange = new Color(1f, 0.45f, 0.1f, 1f); private const string ButtonName = "ExtraHeads Cosmetics Button"; private const string PanelName = "ExtraHeads Cosmetics"; private static GameObject? open; [HarmonyPatch(typeof(MenuManager), "Start")] [HarmonyPostfix] private static void MainMenuButton(MenuManager __instance) { if (!__instance.isInitScene && !((Object)(object)__instance.menuButtons == (Object)null) && !OtherExpanders.Found) { AddButton(__instance.menuButtons.transform); } } [HarmonyPatch(typeof(QuickMenuManager), "Start")] [HarmonyPostfix] private static void PauseMenuButton(QuickMenuManager __instance) { if ((Object)(object)__instance.mainButtonsPanel != (Object)null) { AddButton(__instance.mainButtonsPanel.transform); } } [HarmonyPatch(typeof(QuickMenuManager), "CloseQuickMenu")] [HarmonyPostfix] private static void CloseWithPauseMenu() { Close(); } private static void AddButton(Transform buttons) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_0177: Expected O, but got Unknown CosmeticLibrary.Load(); if (CosmeticLibrary.All.Count == 0 || (Object)(object)buttons.Find("ExtraHeads Cosmetics Button") != (Object)null) { return; } Transform val = ((IEnumerable)buttons).Cast<Transform>().FirstOrDefault((Func<Transform, bool>)delegate(Transform b) { TMP_Text componentInChildren = ((Component)b).GetComponentInChildren<TMP_Text>(true); return componentInChildren != null && componentInChildren.text.ToLowerInvariant().Contains("settings"); }); if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponent<Button>() == (Object)null) { Plugin.Logger.LogWarning((object)("No Settings button in " + ((Object)buttons).name + "; no Cosmetics button there.")); return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, buttons, false); ((Object)val2).name = "ExtraHeads Cosmetics Button"; TMP_Text label = val2.GetComponentInChildren<TMP_Text>(true); label.text = Regex.Replace(label.text, "settings", (Match m) => (!(m.Value == "SETTINGS")) ? ((!(m.Value == "settings")) ? "Cosmetics" : "cosmetics") : "COSMETICS", RegexOptions.IgnoreCase); Button component = val2.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { Open(buttons, label); }); val2.transform.SetSiblingIndex(val.GetSiblingIndex() + 1); if ((Object)(object)((Component)buttons).GetComponent<LayoutGroup>() == (Object)null) { Respace(buttons, (RectTransform)val, (RectTransform)val2.transform); } } private static void Respace(Transform buttons, RectTransform settings, RectTransform ours) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) List<RectTransform> list = (from RectTransform c in (IEnumerable)buttons where (Object)(object)c != (Object)(object)ours && ((Component)c).gameObject.activeSelf && (Object)(object)((Component)c).GetComponentInChildren<Button>() != (Object)null select c).OrderByDescending(RowY).ToList(); if (list.Count < 2 || !list.Contains(settings)) { RectTransform obj = ours; Vector2 anchoredPosition = settings.anchoredPosition; Rect rect = settings.rect; obj.anchoredPosition = anchoredPosition - new Vector2(0f, ((Rect)(ref rect)).height * 1.2f); return; } float num = RowY(list[0]); float num2 = RowY(list[list.Count - 1]); Dictionary<RectTransform, float> dictionary = list.ToDictionary((RectTransform c) => c, RowY); ours.anchoredPosition = settings.anchoredPosition; dictionary[ours] = dictionary[settings]; list.Insert(list.IndexOf(settings) + 1, ours); float num3 = (num - num2) / (float)(list.Count - 1); for (int num4 = 0; num4 < list.Count; num4++) { RectTransform obj2 = list[num4]; obj2.anchoredPosition += new Vector2(0f, num - (float)num4 * num3 - dictionary[list[num4]]); } float RowY(RectTransform row) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return buttons.InverseTransformPoint(((Component)((Component)row).GetComponentInChildren<Button>()).transform.position).y; } } internal static void Open(Transform near, TMP_Text style) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Expected O, but got Unknown //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Expected O, but got Unknown //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Expected O, but got Unknown Close(); Canvas componentInParent = ((Component)near).GetComponentInParent<Canvas>(); Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null); if ((Object)(object)val == (Object)null) { return; } RectTransform val2 = (RectTransform)((Component)val).transform; Rect rect = val2.rect; float height = ((Rect)(ref rect)).height; float num = height * 0.15f; float num2 = height * 0.025f; int num3 = Mathf.CeilToInt((float)CosmeticLibrary.All.Count / 5f); float num4 = 5f * num + 6f * num2; float num5 = height * 0.11f + (float)num3 * num + (float)(num3 - 1) * num2 + height * 0.09f + num2; RectTransform val3 = Rect("ExtraHeads Cosmetics", (Transform)(object)val2, Backdrop); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; Vector2 offsetMin = (val3.offsetMax = Vector2.zero); val3.offsetMin = offsetMin; open = ((Component)val3).gameObject; RectTransform val4 = Rect("Panel", (Transform)(object)val3, Panel); val4.sizeDelta = new Vector2(num4, num5); ((Shadow)((Component)val4).gameObject.AddComponent<Outline>()).effectColor = Orange; Label(val4, "Title", "COSMETICS", style, height * 0.05f, new Vector2(0f, num5 / 2f - height * 0.11f * 0.38f), num4, Orange); Label(val4, "Hint", "Click to wear or take off. Any mix; everyone sees them.", style, height * 0.026f, new Vector2(0f, num5 / 2f - height * 0.11f * 0.82f), num4, new Color(1f, 0.8f, 0.6f)); HashSet<string> worn = new HashSet<string>(Wardrobe.Split(Wardrobe.LocalWorn)); List<(string id, Image bg, Outline edge)> cells = new List<(string, Image, Outline)>(); float num6 = num5 / 2f - height * 0.11f - num / 2f; Vector2 anchoredPosition = default(Vector2); for (int i = 0; i < CosmeticLibrary.All.Count; i++) { CosmeticLibrary.Cosmetic cosmetic = CosmeticLibrary.All[i]; ((Vector2)(ref anchoredPosition))..ctor((0f - num4) / 2f + num2 + num / 2f + (float)(i % 5) * (num + num2), num6 - (float)(i / 5) * (num + num2)); RectTransform val5 = Rect(cosmetic.Id, (Transform)(object)val4, Cell); val5.sizeDelta = new Vector2(num, num); val5.anchoredPosition = anchoredPosition; Outline val6 = ((Component)val5).gameObject.AddComponent<Outline>(); ((Shadow)val6).effectDistance = new Vector2(2f, 2f); if ((Object)(object)cosmetic.Icon != (Object)null) { RectTransform obj = Rect("Icon", (Transform)(object)val5, Color.white); Image component = ((Component)obj).GetComponent<Image>(); component.sprite = cosmetic.Icon; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; obj.sizeDelta = new Vector2(num * 0.6f, num * 0.6f); obj.anchoredPosition = new Vector2(0f, num * 0.17f); } Label(val5, "Name", cosmetic.Name, style, height * 0.024f, new Vector2(0f, (0f - num) * 0.32f), num * 0.94f, Color.white, 2); Button obj2 = ((Component)val5).gameObject.AddComponent<Button>(); ((Selectable)obj2).targetGraphic = (Graphic)(object)((Component)val5).GetComponent<Image>(); string id = cosmetic.Id; ((UnityEvent)obj2.onClick).AddListener((UnityAction)delegate { if (!worn.Remove(id)) { worn.Add(id); } Wardrobe.SetLocal(string.Join(",", worn)); Paint(cells, worn); }); cells.Add((cosmetic.Id, ((Component)val5).GetComponent<Image>(), val6)); } Paint(cells, worn); float num7 = (0f - num5) / 2f + num2 + height * 0.09f * 0.45f; TextButton(val4, "Take all off", style, height, new Vector2((0f - num4) / 4f, num7), (UnityAction)delegate { worn.Clear(); Wardrobe.SetLocal(""); Paint(cells, worn); }); Vector2 pos = new Vector2(num4 / 4f, num7); object obj3 = <>O.<0>__Close; if (obj3 == null) { UnityAction val7 = Close; <>O.<0>__Close = val7; obj3 = (object)val7; } TextButton(val4, "Done", style, height, pos, (UnityAction)obj3); } private static void Paint(List<(string id, Image bg, Outline edge)> cells, HashSet<string> worn) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) foreach (var cell in cells) { string item = cell.id; Image item2 = cell.bg; Outline item3 = cell.edge; bool flag = worn.Contains(item); ((Graphic)item2).color = (flag ? CellWorn : Cell); ((Shadow)item3).effectColor = (flag ? Orange : Color.clear); } } internal static void Close() { if ((Object)(object)open != (Object)null) { Object.Destroy((Object)(object)open); open = null; } } private static RectTransform Rect(string name, Transform parent, Color colour) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); component.pivot = val; Vector2 anchorMin = (component.anchorMax = val); component.anchorMin = anchorMin; ((Graphic)((Component)component).GetComponent<Image>()).color = colour; return component; } private static void Label(RectTransform parent, string name, string text, TMP_Text style, float size, Vector2 pos, float width, Color colour, int lines = 1) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI obj = new GameObject(name, new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>(); RectTransform rectTransform = ((TMP_Text)obj).rectTransform; ((Transform)rectTransform).SetParent((Transform)(object)parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); rectTransform.pivot = val; Vector2 anchorMin = (rectTransform.anchorMax = val); rectTransform.anchorMin = anchorMin; rectTransform.anchoredPosition = pos; rectTransform.sizeDelta = new Vector2(width, size * ((lines == 1) ? 1.4f : (1.2f * (float)lines))); ((TMP_Text)obj).font = style.font; ((TMP_Text)obj).fontSharedMaterial = style.fontSharedMaterial; ((Graphic)obj).color = colour; ((TMP_Text)obj).enableAutoSizing = true; ((TMP_Text)obj).fontSizeMax = size; ((TMP_Text)obj).fontSizeMin = size * ((lines == 1) ? 0.5f : 0.8f); ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((TMP_Text)obj).enableWordWrapping = lines > 1; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).text = text; } private static void TextButton(RectTransform parent, string text, TMP_Text style, float h, Vector2 pos, UnityAction act) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Rect(text, (Transform)(object)parent, Cell); val.sizeDelta = new Vector2(h * 0.26f, h * 0.06f); val.anchoredPosition = pos; ((Shadow)((Component)val).gameObject.AddComponent<Outline>()).effectColor = Orange; Label(val, "Text", text, style, h * 0.032f, Vector2.zero, h * 0.25f, Orange); Button obj = ((Component)val).gameObject.AddComponent<Button>(); ((Selectable)obj).targetGraphic = (Graphic)(object)((Component)val).GetComponent<Image>(); ((UnityEvent)obj.onClick).AddListener(act); } } [HarmonyPatch] internal static class LobbyPicker { private const float ExtraHeight = 34f; private const float RowY = -19f; private const float LabelX = -68f; private const float LabelWidth = 110f; private const float FieldX = 24f; private const float FieldWidth = 48f; private const float RangeX = 88f; private const float RangeWidth = 60f; private const float LabelSize = 13f; private const float RangeSize = 11f; private const int Digits = 2; private const string RowName = "ExtraHeads LobbySize"; private static TMP_InputField? field; [HarmonyPatch(typeof(MenuManager), "Start")] [HarmonyPostfix] private static void AddPicker(MenuManager __instance) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) if (__instance.isInitScene || (Object)(object)__instance.HostSettingsScreen == (Object)null || OtherExpanders.Found) { return; } Transform val = __instance.HostSettingsScreen.transform.Find("HostSettingsContainer"); Transform val2 = ((val != null) ? val.Find("Back") : null); Transform val3 = ((val != null) ? val.Find("Confirm") : null); object obj; if (val == null) { obj = null; } else { Transform obj2 = val.Find("LobbyHostOptions/LANOptions/Header"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<TextMeshProUGUI>() : null); } TextMeshProUGUI val4 = (TextMeshProUGUI)obj; Transform val5 = ((val != null) ? val.Find("LobbyHostOptions/OptionsNormal/ServerNameField") : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val.Find("ExtraHeads LobbySize") != (Object)null) { Plugin.Logger.LogWarning((object)"Host settings screen not as expected; no lobby size box."); return; } RectTransform val6 = (RectTransform)val; val6.sizeDelta += new Vector2(0f, 34f); foreach (Transform item in val) { Transform val7 = item; RectTransform val8 = (RectTransform)val7; if ((Object)(object)val7 == (Object)(object)val3 || (Object)(object)val7 == (Object)(object)val2) { val8.anchoredPosition -= new Vector2(0f, 17f); } else if (((Object)val7).name == "LobbyHostOptions") { val8.anchoredPosition += new Vector2(0f, 17f); } } RectTransform component = new GameObject("ExtraHeads LobbySize", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(val, false); Vector2 val9 = default(Vector2); ((Vector2)(ref val9))..ctor(0.5f, 0.5f); component.pivot = val9; Vector2 anchorMin = (component.anchorMax = val9); component.anchorMin = anchorMin; component.anchoredPosition = new Vector2(0f, -19f); component.sizeDelta = new Vector2(val6.sizeDelta.x, 34f); Text(component, "Label", "Lobby size:", val4, 13f, -68f, 110f, (TextAlignmentOptions)516); Text(component, "Range", $"({1}-{16})", val4, 11f, 88f, 60f, (TextAlignmentOptions)513); field = NumberBox(component, val5); } private static TMP_InputField NumberBox(RectTransform row, Transform template) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown GameObject obj = Object.Instantiate<GameObject>(((Component)template).gameObject, (Transform)(object)row, false); ((Object)obj).name = "Size"; obj.SetActive(true); RectTransform val = (RectTransform)obj.transform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); val.pivot = val2; Vector2 anchorMin = (val.anchorMax = val2); val.anchorMin = anchorMin; val.anchoredPosition = new Vector2(24f, 0f); val.sizeDelta = new Vector2(48f / ((Transform)val).localScale.x, val.sizeDelta.y); TMP_InputField component = obj.GetComponent<TMP_InputField>(); component.onValueChanged = new OnChangeEvent(); component.onEndEdit = new SubmitEvent(); component.onSubmit = new SubmitEvent(); component.contentType = (ContentType)2; component.characterLimit = 2; component.textComponent.alignment = (TextAlignmentOptions)514; Graphic placeholder = component.placeholder; TMP_Text val4 = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null); if (val4 != null) { val4.text = 4.ToString(); val4.alignment = (TextAlignmentOptions)514; } component.text = Plugin.BoundConfig.LobbySize.Value.ToString(); ((UnityEvent<string>)(object)component.onEndEdit).AddListener((UnityAction<string>)Take); return component; } private static void Take(string typed) { ConfigEntry<int> lobbySize = Plugin.BoundConfig.LobbySize; if (int.TryParse(typed, out var result)) { lobbySize.Value = Mathf.Clamp(result, 1, 16); } if ((Object)(object)field != (Object)null) { field.SetTextWithoutNotify(lobbySize.Value.ToString()); } } private static void Text(RectTransform row, string name, string text, TextMeshProUGUI style, float size, float x, float width, TextAlignmentOptions align) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI obj = new GameObject(name, new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>(); RectTransform rectTransform = ((TMP_Text)obj).rectTransform; ((Transform)rectTransform).SetParent((Transform)(object)row, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); rectTransform.pivot = val; Vector2 anchorMin = (rectTransform.anchorMax = val); rectTransform.anchorMin = anchorMin; rectTransform.anchoredPosition = new Vector2(x, 0f); rectTransform.sizeDelta = new Vector2(width, row.sizeDelta.y); ((TMP_Text)obj).font = ((TMP_Text)style).font; ((TMP_Text)obj).fontSharedMaterial = ((TMP_Text)style).fontSharedMaterial; ((Graphic)obj).color = ((Graphic)style).color; ((TMP_Text)obj).fontSize = size; ((TMP_Text)obj).alignment = align; ((TMP_Text)obj).enableWordWrapping = false; ((TMP_Text)obj).text = text; } } [HarmonyPatch] internal static class PlayerList { private const float RowSpacing = 64f; private const float RowTop = 64f; private const float ListTop = 58f; private const float ListBottom = 10f; private const float ScrollSpeed = 24f; private const string ListName = "ExtraHeads Crew"; private static TextMeshProUGUI? header; private static RectTransform? rows; [HarmonyPatch(typeof(QuickMenuManager), "Start")] [HarmonyPostfix] private static void ListEveryone(QuickMenuManager __instance) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: 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_028a: Unknown result type (might be due to invalid IL or missing references) if (!LobbySize.Expanded) { return; } PlayerListSlot[] playerListSlots = __instance.playerListSlots; Transform val = __instance.playerListPanel.transform.Find("Image"); object obj; if (val == null) { obj = null; } else { Transform obj2 = val.Find("Header"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<TextMeshProUGUI>() : null); } header = (TextMeshProUGUI?)obj; if ((Object)(object)val == (Object)null || playerListSlots.Length == 0 || (Object)(object)playerListSlots[0].slotContainer == (Object)null || (Object)(object)val.Find("ExtraHeads Crew") != (Object)null) { Plugin.Logger.LogWarning((object)"Pause-menu crew list not as expected; extra players get no rows."); return; } RectTransform component = new GameObject("ExtraHeads Crew", new Type[4] { typeof(RectTransform), typeof(Image), typeof(RectMask2D), typeof(ScrollRect) }).GetComponent<RectTransform>(); ((Graphic)((Component)component).GetComponent<Image>()).color = Color.clear; ((Transform)component).SetParent(val, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(0f, 10f); component.offsetMax = new Vector2(0f, -58f); RectTransform component2 = new GameObject("Rows", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component2).SetParent((Transform)(object)component, false); component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(0.5f, 1f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = new Vector2(0f, (float)LobbySize.Slots * 64f); rows = component2; ScrollRect component3 = ((Component)component).GetComponent<ScrollRect>(); component3.content = component2; component3.viewport = component; component3.horizontal = false; component3.movementType = (MovementType)2; component3.scrollSensitivity = 24f; int num = playerListSlots.Length; Array.Resize(ref __instance.playerListSlots, LobbySize.Slots); GameObject slotContainer = playerListSlots[num - 1].slotContainer; Vector2 val3 = default(Vector2); for (int i = 0; i < LobbySize.Slots; i++) { if (i >= num) { __instance.playerListSlots[i] = CopyRow(__instance, slotContainer, i); } RectTransform val2 = (RectTransform)__instance.playerListSlots[i].slotContainer.transform; ((Transform)val2).SetParent((Transform)(object)component2, false); ((Vector2)(ref val3))..ctor(0.5f, 1f); val2.anchorMax = val3; val2.anchorMin = val3; val2.anchoredPosition = new Vector2(val2.anchoredPosition.x, -64f - (float)i * 64f); } } private static PlayerListSlot CopyRow(QuickMenuManager menu, GameObject template, int slot) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(template, template.transform.parent, false); ((Object)val).name = $"PlayerListSlot ({slot})"; val.SetActive(false); PlayerListSlot entry = new PlayerListSlot { slotContainer = val, usernameHeader = ((Component)val.transform.Find("PlayerNameButton/PName")).GetComponent<TextMeshProUGUI>(), volumeSliderContainer = ((Component)val.transform.Find("VoiceVolumeSlider")).gameObject, volumeSlider = ((Component)val.transform.Find("VoiceVolumeSlider/Slider")).GetComponent<Slider>(), KickUserButton = ((Component)val.transform.Find("KickButton")).gameObject, isConnected = false }; Button component = entry.KickUserButton.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { menu.KickUserFromServer(slot); }); Transform obj = val.transform.Find("ProfileIcon"); Button val2 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null); if ((Object)(object)val2 != (Object)null) { val2.onClick = new ButtonClickedEvent(); ((UnityEvent)val2.onClick).AddListener((UnityAction)delegate { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!GameNetworkManager.Instance.disableSteam && entry.playerSteamId != 0L) { SteamFriends.OpenUserOverlay(SteamId.op_Implicit(entry.playerSteamId), "steamid"); } }); } return entry; } [HarmonyPatch(typeof(QuickMenuManager), "Update")] [HarmonyPostfix] private static void CountCrew(QuickMenuManager __instance) { //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)header == (Object)null || !LobbySize.Expanded || !__instance.isMenuOpen) { return; } int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? (StartOfRound.Instance.connectedPlayersAmount + 1) : 0); PlayerListSlot[] playerListSlots = __instance.playerListSlots; for (int i = 0; i < Preview.Players && i < playerListSlots.Length; i++) { if (!playerListSlots[i].isConnected) { playerListSlots[i].slotContainer.SetActive(true); ((TMP_Text)playerListSlots[i].usernameHeader).text = Preview.Name(i); } } ((TMP_Text)header).text = $"CREW: {Mathf.Max(num, Preview.Players)} / {LobbySize.Slots}"; if ((Object)(object)rows == (Object)null) { return; } int num2 = 0; PlayerListSlot[] array = playerListSlots; foreach (PlayerListSlot val in array) { if ((Object)(object)val.slotContainer != (Object)null && val.slotContainer.activeSelf) { RectTransform val2 = (RectTransform)val.slotContainer.transform; val2.anchoredPosition = new Vector2(val2.anchoredPosition.x, -64f - (float)num2 * 64f); num2++; } } rows.sizeDelta = new Vector2(0f, (float)num2 * 64f + 10f); } } internal static class Preview { internal static int Players => 0; internal static int ExtraResults(int crew) { return Mathf.Max(0, Players - crew); } internal static string Name(int slot) { return $"Employee #{slot}"; } } [HarmonyPatch] internal static class ResultsGrid { private static readonly Vector2 AreaCentre = new Vector2(8f, 11f); private static readonly Vector2 AreaSize = new Vector2(402f, 210f); private const int Columns = 4; private const float CellGap = 4f; private const float Padding = 4f; private const float NameSize = 12f; private const float NoteSize = 9f; private static readonly Vector2 IconSize = new Vector2(24f, 14f); private static readonly Color Backing = new Color(0.27f, 0.02f, 0.02f, 1f); private const float BorderWidth = 1.5f; private const string GridName = "ExtraHeads Results"; [HarmonyPatch(typeof(HUDManager), "FillEndGameStats")] [HarmonyPostfix] private static void FillGrid(HUDManager __instance, EndOfGameStats stats) { //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Invalid comparison between Unknown and I4 //IL_029a: Unknown result type (might be due to invalid IL or missing references) EndOfGameStatUIElements statsUIElements = __instance.statsUIElements; object obj; if (statsUIElements.playerNamesText.Length == 0) { obj = null; } else { Transform parent = ((TMP_Text)statsUIElements.playerNamesText[0]).transform.parent; obj = ((parent != null) ? parent.parent : null); } Transform val = (Transform)obj; if ((Object)(object)val == (Object)null) { return; } List<int> list = new List<int>(); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; for (int i = 0; i < allPlayerScripts.Length; i++) { if (allPlayerScripts[i].disconnectedMidGame || allPlayerScripts[i].isPlayerDead || allPlayerScripts[i].isPlayerControlled) { list.Add(i); } } bool flag = list.Count + Preview.ExtraResults(list.Count) > 4; for (int j = 0; j < statsUIElements.playerNamesText.Length; j++) { ((Component)((TMP_Text)statsUIElements.playerNamesText[j]).transform.parent).gameObject.SetActive(!flag); } Transform val2 = val.Find("ExtraHeads Results"); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } if (!flag) { return; } RectTransform parent2 = Box(val, "ExtraHeads Results", AreaCentre, AreaSize, Backing); int num = list.Count + Preview.ExtraResults(list.Count); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)num / 4f)); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor((AreaSize.x - 20f) / 4f, (AreaSize.y - 4f * (float)(num2 + 1)) / (float)num2); TextMeshProUGUI val4 = statsUIElements.playerNamesText[0]; Vector2 centre = default(Vector2); for (int k = 0; k < num; k++) { int num3 = k % 4; int num4 = k / 4; ((Vector2)(ref centre))..ctor((0f - AreaSize.x) / 2f + 4f + val3.x / 2f + (float)num3 * (val3.x + 4f), AreaSize.y / 2f - 4f - val3.y / 2f - (float)num4 * (val3.y + 4f)); RectTransform frame = Box((Transform)(object)parent2, $"Cell {k}", centre, val3, Color.clear); Outline(frame, ((Graphic)val4).color); if (k < list.Count) { PlayerControllerB val5 = allPlayerScripts[list[k]]; List<string> playerNotes = stats.allPlayerStats[list[k]].playerNotes; Sprite icon = ((!val5.isPlayerDead) ? statsUIElements.aliveIcon : (((int)val5.causeOfDeath == 10) ? statsUIElements.missingIcon : statsUIElements.deceasedIcon)); Fill(frame, val3, val4, val5.playerUsername, icon, (playerNotes.Count > 0) ? playerNotes[0] : ""); } else { Fill(frame, val3, val4, Preview.Name(k), (k % 3 == 0) ? statsUIElements.deceasedIcon : statsUIElements.aliveIcon, (k % 2 == 0) ? "Most paranoid employee" : ""); } } } private static void Fill(RectTransform frame, Vector2 cell, TextMeshProUGUI style, string name, Sprite icon, string note) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) Text(frame, "Name", name, style, 12f, new Vector2(0f, cell.y / 2f - 4f - 6f), new Vector2(cell.x - 8f, 14f)); Image component = ((Component)Box((Transform)(object)frame, "State", new Vector2(cell.x / 2f - 4f - IconSize.x / 2f, (0f - cell.y) / 2f + 4f + IconSize.y / 2f), IconSize, ((Graphic)style).color)).GetComponent<Image>(); component.sprite = icon; component.preserveAspect = true; if (note.Length > 0) { float num = cell.x - IconSize.x - 12f; Text(frame, "Note", "* " + note, style, 9f, new Vector2((0f - cell.x) / 2f + 4f + num / 2f, (0f - cell.y) / 2f + 4f + 9f), new Vector2(num, 20f)); } } private static RectTransform Box(Transform parent, string name, Vector2 centre, Vector2 size, Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); component.pivot = val; Vector2 anchorMin = (component.anchorMax = val); component.anchorMin = anchorMin; component.anchoredPosition = centre; component.sizeDelta = size; ((Graphic)((Component)component).GetComponent<Image>()).color = color; return component; } private static void Outline(RectTransform frame, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) Vector2 sizeDelta = frame.sizeDelta; Box((Transform)(object)frame, "Top", new Vector2(0f, sizeDelta.y / 2f), new Vector2(sizeDelta.x, 1.5f), color); Box((Transform)(object)frame, "Bottom", new Vector2(0f, (0f - sizeDelta.y) / 2f), new Vector2(sizeDelta.x, 1.5f), color); Box((Transform)(object)frame, "Left", new Vector2((0f - sizeDelta.x) / 2f, 0f), new Vector2(1.5f, sizeDelta.y), color); Box((Transform)(object)frame, "Right", new Vector2(sizeDelta.x / 2f, 0f), new Vector2(1.5f, sizeDelta.y), color); } private static void Text(RectTransform parent, string name, string text, TextMeshProUGUI style, float size, Vector2 centre, Vector2 box) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI obj = new GameObject(name, new Type[1] { typeof(RectTransform) }).AddComponent<TextMeshProUGUI>(); RectTransform rectTransform = ((TMP_Text)obj).rectTransform; ((Transform)rectTransform).SetParent((Transform)(object)parent, false); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); rectTransform.pivot = val; Vector2 anchorMin = (rectTransform.anchorMax = val); rectTransform.anchorMin = anchorMin; rectTransform.anchoredPosition = centre; rectTransform.sizeDelta = box; ((TMP_Text)obj).font = ((TMP_Text)style).font; ((TMP_Text)obj).fontSharedMaterial = ((TMP_Text)style).fontSharedMaterial; ((Graphic)obj).color = ((Graphic)style).color; ((TMP_Text)obj).fontSize = size; ((TMP_Text)obj).alignment = (TextAlignmentOptions)257; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; ((TMP_Text)obj).text = text; } } [HarmonyPatch] internal static class SpectatorList { private const float RowSpacing = 70f; private const float FirstX = -64f; private const float FirstY = 0f; private const int RowsPerColumn = 5; private const float ColumnSpacing = 170f; private static readonly Dictionary<int, RectTransform> previewBoxes = new Dictionary<int, RectTransform>(); [HarmonyPatch(typeof(HUDManager), "UpdateBoxesSpectateUI")] [HarmonyPostfix] private static void WrapIntoColumns(HUDManager __instance, Dictionary<Animator, PlayerControllerB> ___spectatingPlayerBoxes) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (LobbySize.Expanded) { List<RectTransform> list = (from box in (from pair in ___spectatingPlayerBoxes where (Object)(object)pair.Key != (Object)null && ((Component)pair.Key).gameObject.activeSelf select ((int, RectTransform))((int)pair.Value.playerClientId, (RectTransform)((Component)pair.Key).transform)).Concat<(int, RectTransform)>(PreviewBoxes(__instance)) orderby box.Item1 select box.Item2).ToList(); for (int num = 0; num < list.Count; num++) { int num2 = num / 5; int num3 = num % 5; list[num].anchoredPosition = new Vector2(-64f + (float)num2 * 170f, 0f - (float)num3 * 70f); } } } private static IEnumerable<(int, RectTransform)> PreviewBoxes(HUDManager hud) { PlayerControllerB[] players = StartOfRound.Instance.allPlayerScripts; for (int slot = 0; slot < Preview.Players && slot < players.Length; slot++) { if (!players[slot].isPlayerControlled && !players[slot].isPlayerDead) { if (!previewBoxes.TryGetValue(slot, out RectTransform value) || (Object)(object)value == (Object)null) { GameObject val = Object.Instantiate<GameObject>(hud.spectatingPlayerBoxPrefab, hud.SpectateBoxesContainer, false); val.SetActive(true); ((TMP_Text)val.GetComponentInChildren<TextMeshProUGUI>()).text = Preview.Name(slot); Dictionary<int, RectTransform> dictionary = previewBoxes; int key = slot; RectTransform val2 = (RectTransform)val.transform; value = val2; dictionary[key] = val2; } yield return (slot, value); } } } } } namespace ExtraHeads.Cosmetics { internal static class CosmeticLibrary { internal sealed class Piece { public string Role = ""; public Vector3 Pivot; public Vector3 Axis; public Mesh Mesh; public int[] MaterialIds; } internal sealed class Cosmetic { public string Id = ""; public string Name = ""; public string Spot = ""; public string Bone = ""; public string Motion = ""; public Vector3 Base; public Vector3 Up; public Vector3 Forward; public List<Piece> Pieces = new List<Piece>(); public Sprite? Icon; } private struct MaterialSpec { public string Name; public Color Colour; public float Emit; public float Rough; public float Metal; public float Alpha; } private const float EmissionScale = 40f; internal static readonly List<Cosmetic> All = new List<Cosmetic>(); internal static readonly Dictionary<string, Cosmetic> ById = new Dictionary<string, Cosmetic>(); private static readonly List<MaterialSpec> specs = new List<MaterialSpec>(); private static Material[]? materials; internal static bool Loaded { get; private set; } private static string Folder => Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "Assets"); internal static void Load() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (Loaded) { return; } Loaded = true; string text = Path.Combine(Folder, "cosmetics.bin"); if (!File.Exists(text)) { Plugin.Logger.LogWarning((object)("No cosmetics file at " + text + "; cosmetics are off.")); return; } try { using GZipStream input = new GZipStream(File.OpenRead(text), CompressionMode.Decompress); using BinaryReader binaryReader = new BinaryReader(input); if (new string(binaryReader.ReadChars(4)) != "EHC2") { Plugin.Logger.LogWarning((object)"Cosmetics file is from another version; cosmetics are off."); return; } int num = binaryReader.ReadInt32(); for (int i = 0; i < num; i++) { specs.Add(new MaterialSpec { Name = binaryReader.ReadString(), Colour = new Color(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()), Emit = binaryReader.ReadSingle(), Rough = binaryReader.ReadSingle(), Metal = binaryReader.ReadSingle(), Alpha = binaryReader.ReadSingle() }); } int num2 = binaryReader.ReadInt32(); for (int j = 0; j < num2; j++) { Cosmetic cosmetic = new Cosmetic { Id = binaryReader.ReadString(), Name = binaryReader.ReadString(), Spot = binaryReader.ReadString(), Bone = binaryReader.ReadString(), Motion = binaryReader.ReadString(), Base = ReadVector(binaryReader), Up = ReadVector(binaryReader), Forward = ReadVector(binaryReader) }; int num3 = binaryReader.ReadInt32(); for (int k = 0; k < num3; k++) { cosmetic.Pieces.Add(ReadPiece(binaryReader, cosmetic.Id)); } cosmetic.Icon = LoadIcon(cosmetic.Id); All.Add(cosmetic); ById[cosmetic.Id] = cosmetic; } Plugin.Logger.LogInfo((object)$"Loaded {All.Count} cosmetics."); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Couldn't read the cosmetics file; cosmetics are off. {arg}"); All.Clear(); ById.Clear(); } } private static Piece ReadPiece(BinaryReader r, string id) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown Piece piece = new Piece { Role = r.ReadString(), Pivot = ReadVector(r), Axis = ReadVector(r) }; int num = r.ReadInt32(); Vector3[] array = (Vector3[])(object)new Vector3[num]; Vector3[] array2 = (Vector3[])(object)new Vector3[num]; for (int i = 0; i < num; i++) { array[i] = ReadVector(r) - piece.Pivot; array2[i] = ReadVector(r); } int num2 = r.ReadInt32(); Mesh val = new Mesh { name = "ExtraHeads " + id + " " + piece.Role }; val.indexFormat = (IndexFormat)(num > 65000); val.vertices = array; val.normals = array2; val.subMeshCount = num2; piece.MaterialIds = new int[num2]; for (int j = 0; j < num2; j++) { piece.MaterialIds[j] = r.ReadInt32(); int[] array3 = new int[r.ReadInt32()]; for (int k = 0; k < array3.Length; k++) { array3[k] = r.ReadInt32(); } val.SetTriangles(array3, j); } val.RecalculateBounds(); val.UploadMeshData(true); piece.Mesh = val; return piece; } private static Vector3 ReadVector(BinaryReader r) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); } private static Sprite? LoadIcon(string id) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) string path = Path.Combine(Folder, "icons", id + ".png"); if (!File.Exists(path)) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { name = "ExtraHeads icon " + id }; if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path), true)) { return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } internal static Material[] Materials(Material source) { if (materials != null) { return materials; } materials = (Material[]?)(object)new Material[specs.Count]; for (int i = 0; i < specs.Count; i++) { materials[i] = MakeMaterial(source, specs[i]); } Plugin.Logger.LogInfo((object)("Cosmetic materials made from '" + ((Object)source).name + "' (" + ((Object)source.shader).name + ").")); return materials; } private static Material MakeMaterial(Material source, MaterialSpec spec) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(source) { name = "ExtraHeads " + spec.Name }; string[] array = new string[6] { "_BaseColorMap", "_MainTex", "_MaskMap", "_NormalMap", "_EmissiveColorMap", "_DetailMap" }; foreach (string text in array) { if (val.HasProperty(text)) { val.SetTexture(text, (Texture)null); } } array = new string[5] { "_MASKMAP", "_NORMALMAP", "_NORMALMAP_TANGENT_SPACE", "_EMISSIVE_COLOR_MAP", "_DETAIL_MAP" }; foreach (string text2 in array) { val.DisableKeyword(text2); } Color colour = spec.Colour; float value = 1f - spec.Rough; float value2 = spec.Metal; if (spec.Alpha < 0.5f) { ((Color)(ref colour))..ctor(0.08f, 0.1f, 0.12f); value = 0.95f; value2 = 0.6f; } Set(val, "_BaseColor", ((Color)(ref colour)).gamma); Set(val, "_Color", ((Color)(ref colour)).gamma); Set(val, "_Metallic", value2); Set(val, "_Smoothness", value); Set(val, "_SmoothnessRemapMax", value); Set(val, "_SmoothnessRemapMin", 0f); Set(val, "_MetallicRemapMax", value2); Set(val, "_MetallicRemapMin", 0f); Color value3; if (!(spec.Emit > 0f)) { value3 = Color.bla