using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks.CompilerServices; using Gamemode_Lib.ConfigSync; using Gamemode_Lib.Events; using Gamemode_Lib.Network.Messages; using Gamemode_Lib.Patches; using Gamemode_Lib.Patches.Features; using Gamemode_Lib.Teams; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Pool; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("GameAssembly")] [assembly: IgnoresAccessChecksTo("SharedAssembly")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.glarmer.Gamemode_Lib")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.5.1.0")] [assembly: AssemblyInformationalVersion("0.5.1+9d9bdcb58e0a52d8479020bb6fdc773de9ffa3c1")] [assembly: AssemblyProduct("com.github.glarmer.Gamemode_Lib")] [assembly: AssemblyTitle("Gamemode_Lib")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] 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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace Gamemode_Lib { public static class GameModeUtilities { public static Dictionary Modes { get; } = new Dictionary(); public static string? CurrentGamemodeId { get; set; } public static bool GameEnded { get; set; } = true; public static void ReinitializeGameState() { string currentGamemodeId = CurrentGamemodeId; Plugin.Log.LogInfo((object)($"[GamemodeLib] ReinitializeGameState: serverActive={NetworkServer.active} clientActive={NetworkClient.active} " + string.Format("gameEnded={0} currentGamemodeId='{1}'", GameEnded, currentGamemodeId ?? ""))); if (currentGamemodeId != null && Modes.TryGetValue(currentGamemodeId, out IGamemode value) && value != null) { try { Harmony gamemodeHarmony = value.GamemodeHarmony; if (gamemodeHarmony != null) { gamemodeHarmony.UnpatchSelf(); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"[GamemodeLib] ReinitializeGameState: failed to unpatch gamemode harmony for '{currentGamemodeId}': {arg}"); } } ConfigSyncManager.Instance?.ClearAllScopes(); bool active = NetworkServer.active; TeamManager.Instance?.ResetToDefaults(active); CurrentGamemodeId = null; GameEnded = true; } public static void RegisterGameMode(IGamemode gamemode) { if (Modes != null) { if (Modes.ContainsKey(gamemode.GameModeId)) { Plugin.Log.LogError((object)("Gamemode with same ID: " + gamemode.GameModeId + " has already been registered! We will not re-register...")); return; } Modes.Add(gamemode.GameModeId, gamemode); _ = gamemode.IsTeamBased; Plugin.Log.LogInfo((object)("Gamemode ID: " + gamemode.GameModeId + " has been registered!")); } else { Plugin.Log.LogError((object)("Gamemode dictionary was null! " + gamemode.Name + " is not loaded...")); } } public static void ApplyGamemodeStartMessage(GamemodeStartMessage message) { Plugin.Log.LogInfo((object)($"[GamemodeLib] ApplyGamemodeStartMessage: serverActive={NetworkServer.active} clientActive={NetworkClient.active} " + string.Format("gameEnded={0} currentGamemodeId='{1}' msgGamemodeId='{2}'", GameEnded, CurrentGamemodeId ?? "", message.GamemodeId ?? ""))); if (NetworkServer.active) { Plugin.Log.LogInfo((object)"[GamemodeLib] ApplyGamemodeStartMessage: ignoring because server is active"); return; } if (message.GamemodeId == null) { Plugin.Log.LogError((object)"[GamemodeLib] Received GamemodeStartMessage with null GamemodeId"); return; } if (!Modes.TryGetValue(message.GamemodeId, out IGamemode value) || value == null) { Plugin.Log.LogError((object)$"[GamemodeLib] Received GamemodeStartMessage for unknown mode id '{message.GamemodeId}'. modesCount={Modes.Count}"); return; } Plugin.Log.LogInfo((object)("[GamemodeLib] ApplyGamemodeStartMessage: starting mode '" + message.GamemodeId + "'. " + string.Format("previousState: gameEnded={0} currentGamemodeId='{1}'", GameEnded, CurrentGamemodeId ?? ""))); CurrentGamemodeId = message.GamemodeId; GameEnded = false; if ((Object)(object)ConfigSyncManager.Instance != (Object)null && !ConfigSyncManager.Instance.HasReceivedFull(message.GamemodeId)) { ConfigSyncManager.Instance.RequestScopeFromHost(message.GamemodeId); } try { value.OnGameStart(); Plugin.Log.LogInfo((object)("[GamemodeLib] ApplyGamemodeStartMessage: mode.OnGameStart() finished for '" + message.GamemodeId + "'")); } catch (Exception arg) { Plugin.Log.LogError((object)$"[GamemodeLib] ApplyGamemodeStartMessage: mode.OnGameStart() threw for '{message.GamemodeId}': {arg}"); throw; } } public static void ApplyGamemodeEndMessage(GamemodeEndMessage message) { Plugin.Log.LogInfo((object)($"[GamemodeLib] ApplyGamemodeEndMessage: serverActive={NetworkServer.active} clientActive={NetworkClient.active} " + string.Format("gameEnded={0} currentGamemodeId='{1}' msgGamemodeId='{2}'", GameEnded, CurrentGamemodeId ?? "", message.GamemodeId ?? ""))); if (NetworkServer.active) { Plugin.Log.LogInfo((object)"[GamemodeLib] ApplyGamemodeEndMessage: ignoring because server is active"); return; } if (GameEnded) { Plugin.Log.LogInfo((object)"[GamemodeLib] ApplyGamemodeEndMessage: ignoring because GameEnded is already true"); return; } if (message.GamemodeId == null) { Plugin.Log.LogError((object)"[GamemodeLib] Received GamemodeEndMessage with null GamemodeId"); return; } if (!Modes.TryGetValue(message.GamemodeId, out IGamemode value) || value == null) { Plugin.Log.LogError((object)("[GamemodeLib] Received GamemodeEndMessage for unknown mode id '" + message.GamemodeId + "'. " + $"modesCount={Modes.Count}. Forcing local end state.")); GameEnded = true; CurrentGamemodeId = null; return; } Plugin.Log.LogInfo((object)("[GamemodeLib] ApplyGamemodeEndMessage: ending mode '" + message.GamemodeId + "'. " + string.Format("previousState: gameEnded={0} currentGamemodeId='{1}'", GameEnded, CurrentGamemodeId ?? ""))); CurrentGamemodeId = message.GamemodeId; GameEnded = true; try { value.OnGameEnd(); Plugin.Log.LogInfo((object)("[GamemodeLib] ApplyGamemodeEndMessage: mode.OnGameEnd() finished for '" + message.GamemodeId + "'")); } catch (Exception arg) { Plugin.Log.LogError((object)$"[GamemodeLib] ApplyGamemodeEndMessage: mode.OnGameEnd() threw for '{message.GamemodeId}': {arg}"); throw; } CurrentGamemodeId = null; ConfigSyncManager.Instance?.ClearScope(message.GamemodeId); Plugin.Log.LogInfo((object)"[GamemodeLib] ApplyGamemodeEndMessage: cleared CurrentGamemodeId and set GameEnded=true"); } internal static void TryEndCurrentGame(bool broadcastToClients) { Plugin.Log.LogInfo((object)($"[GamemodeLib] TryEndCurrentGame: broadcastToClients={broadcastToClients} serverActive={NetworkServer.active} clientActive={NetworkClient.active} " + string.Format("gameEnded={0} currentGamemodeId='{1}'", GameEnded, CurrentGamemodeId ?? ""))); if (GameEnded) { Plugin.Log.LogInfo((object)"[GamemodeLib] TryEndCurrentGame: no-op because GameEnded is already true"); return; } string currentGamemodeId = CurrentGamemodeId; if (currentGamemodeId == null) { Plugin.Log.LogWarning((object)"[GamemodeLib] TryEndCurrentGame: CurrentGamemodeId was null while GameEnded=false; forcing GameEnded=true"); GameEnded = true; return; } if (!Modes.TryGetValue(currentGamemodeId, out IGamemode value) || value == null) { Plugin.Log.LogWarning((object)($"[GamemodeLib] TryEndCurrentGame: mode lookup failed for id '{currentGamemodeId}'. modesCount={Modes.Count}. " + "Forcing GameEnded=true and clearing CurrentGamemodeId.")); GameEnded = true; CurrentGamemodeId = null; return; } Plugin.Log.LogInfo((object)("[GamemodeLib] TryEndCurrentGame: ending current mode '" + currentGamemodeId + "' (modeType=" + value.GetType().FullName + ")")); GameEnded = true; try { value.OnGameEnd(); Plugin.Log.LogInfo((object)("[GamemodeLib] TryEndCurrentGame: mode.OnGameEnd() finished for '" + currentGamemodeId + "'")); } catch (Exception arg) { Plugin.Log.LogError((object)$"[GamemodeLib] TryEndCurrentGame: mode.OnGameEnd() threw for '{currentGamemodeId}': {arg}"); throw; } finally { if (broadcastToClients && NetworkServer.active) { Plugin.Log.LogInfo((object)("[GamemodeLib] TryEndCurrentGame: broadcasting GamemodeEndMessage to all clients for '" + currentGamemodeId + "'")); NetworkMessageBootstrap.Register(); NetworkServer.SendToAll(new GamemodeEndMessage { GamemodeId = currentGamemodeId }, 0, false); Plugin.Log.LogInfo((object)("[GamemodeLib] TryEndCurrentGame: broadcast sent for '" + currentGamemodeId + "'")); } else { Plugin.Log.LogInfo((object)$"[GamemodeLib] TryEndCurrentGame: not broadcasting (broadcastToClients={broadcastToClients}, serverActive={NetworkServer.active})"); } ConfigSyncManager.Instance?.ClearScope(currentGamemodeId); CurrentGamemodeId = null; Plugin.Log.LogInfo((object)"[GamemodeLib] TryEndCurrentGame: cleared CurrentGamemodeId"); } } } public interface IGamemode { Harmony GamemodeHarmony { get; init; } string Name { get; } string ModId { get; } string GameModeId => ModId + ":" + Name; int MinPlayers { get; } int MaxPlayers { get; } bool IsTeamBased { get; } bool IsNormalStartProcedure { get; } bool IsTaggingEnabled { get; } int TeamCount { get; } string Description { get; } void OnGameStart(); void OnGameEnd(); bool CanStart(int playerCount); } public static class NetworkMessageBootstrap { private static bool _commonRegistered; private static bool _clientRegistered; private static bool _serverRegistered; public static void Register() { Plugin.Log.LogInfo((object)($"[GamemodeLib] NetworkMessageBootstrap.Register: clientActive={NetworkClient.active} serverActive={NetworkServer.active} " + $"commonRegistered={_commonRegistered} clientRegistered={_clientRegistered} serverRegistered={_serverRegistered}")); RegisterCommon(); if (NetworkClient.active) { RegisterClient(); } if (NetworkServer.active) { RegisterServer(); } } private static void RegisterCommon() { if (_commonRegistered) { Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterCommon: already registered"); return; } _commonRegistered = true; Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterCommon: registering readers/writers"); Writer.write = delegate(NetworkWriter writer, TeamAssignMessage msg) { NetworkWriterExtensions.WriteULong(writer, msg.PlayerGuid); NetworkWriterExtensions.WriteInt(writer, msg.TeamId); }; Reader.read = (NetworkReader reader) => new TeamAssignMessage { PlayerGuid = NetworkReaderExtensions.ReadULong(reader), TeamId = NetworkReaderExtensions.ReadInt(reader) }; Writer.write = delegate(NetworkWriter writer, TeamRequestMessage msg) { NetworkWriterExtensions.WriteULong(writer, msg.PlayerGuid); }; Reader.read = (NetworkReader reader) => new TeamRequestMessage { PlayerGuid = NetworkReaderExtensions.ReadULong(reader) }; Writer.write = delegate(NetworkWriter writer, TeamDefinitionMessage msg) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) NetworkWriterExtensions.WriteInt(writer, msg.ID); NetworkWriterExtensions.WriteColor(writer, msg.Color); NetworkWriterExtensions.WriteString(writer, msg.Name); }; Reader.read = (NetworkReader reader) => new TeamDefinitionMessage { ID = NetworkReaderExtensions.ReadInt(reader), Color = NetworkReaderExtensions.ReadColor(reader), Name = NetworkReaderExtensions.ReadString(reader) }; Writer.write = delegate(NetworkWriter writer, GamemodeStartMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.GamemodeId); }; Reader.read = (NetworkReader reader) => new GamemodeStartMessage { GamemodeId = NetworkReaderExtensions.ReadString(reader) }; Writer.write = delegate(NetworkWriter writer, GamemodeEndMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.GamemodeId); }; Reader.read = (NetworkReader reader) => new GamemodeEndMessage { GamemodeId = NetworkReaderExtensions.ReadString(reader) }; Writer.write = delegate(NetworkWriter writer, RaycastRequestMessage msg) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) NetworkWriterExtensions.WriteString(writer, msg.Purpose); NetworkWriterExtensions.WriteULong(writer, msg.Guid); NetworkWriterExtensions.WriteVector3(writer, msg.Origin); NetworkWriterExtensions.WriteVector3(writer, msg.Direction); NetworkWriterExtensions.WriteFloat(writer, msg.MaxDistance); NetworkWriterExtensions.WriteInt(writer, msg.RaycastMask); }; Reader.read = (NetworkReader reader) => new RaycastRequestMessage { Purpose = NetworkReaderExtensions.ReadString(reader), Guid = NetworkReaderExtensions.ReadULong(reader), Origin = NetworkReaderExtensions.ReadVector3(reader), Direction = NetworkReaderExtensions.ReadVector3(reader), MaxDistance = NetworkReaderExtensions.ReadFloat(reader), RaycastMask = NetworkReaderExtensions.ReadInt(reader) }; Writer.write = delegate(NetworkWriter writer, RaycastResultMessage msg) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0062: Unknown result type (might be due to invalid IL or missing references) NetworkWriterExtensions.WriteString(writer, msg.Purpose); NetworkWriterExtensions.WriteULong(writer, msg.Guid); NetworkWriterExtensions.WriteVector3(writer, msg.Origin); NetworkWriterExtensions.WriteVector3(writer, msg.Direction); NetworkWriterExtensions.WriteFloat(writer, msg.MaxDistance); NetworkWriterExtensions.WriteInt(writer, msg.RaycastMask); NetworkWriterExtensions.WriteBool(writer, msg.HasHit); NetworkWriterExtensions.WriteVector3(writer, msg.HitPoint); NetworkWriterExtensions.WriteVector3(writer, msg.HitNormal); NetworkWriterExtensions.WriteFloat(writer, msg.HitDistance); NetworkWriterExtensions.WriteString(writer, msg.HitObjectName); NetworkWriterExtensions.WriteString(writer, msg.ClosestValidRootObjectName); }; Reader.read = (NetworkReader reader) => new RaycastResultMessage { Purpose = NetworkReaderExtensions.ReadString(reader), Guid = NetworkReaderExtensions.ReadULong(reader), Origin = NetworkReaderExtensions.ReadVector3(reader), Direction = NetworkReaderExtensions.ReadVector3(reader), MaxDistance = NetworkReaderExtensions.ReadFloat(reader), RaycastMask = NetworkReaderExtensions.ReadInt(reader), HasHit = NetworkReaderExtensions.ReadBool(reader), HitPoint = NetworkReaderExtensions.ReadVector3(reader), HitNormal = NetworkReaderExtensions.ReadVector3(reader), HitDistance = NetworkReaderExtensions.ReadFloat(reader), HitObjectName = NetworkReaderExtensions.ReadString(reader), ClosestValidRootObjectName = NetworkReaderExtensions.ReadString(reader) }; Writer.write = delegate(NetworkWriter writer, ConfigScopeRequestMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.ScopeId); }; Reader.read = (NetworkReader reader) => new ConfigScopeRequestMessage { ScopeId = NetworkReaderExtensions.ReadString(reader) }; Writer.write = delegate(NetworkWriter writer, ConfigEntry entry) { NetworkWriterExtensions.WriteString(writer, entry.Key); writer.WriteByte((byte)entry.Type); switch (entry.Type) { case ConfigValueType.String: NetworkWriterExtensions.WriteString(writer, entry.StringValue); break; case ConfigValueType.Int: NetworkWriterExtensions.WriteInt(writer, entry.IntValue); break; case ConfigValueType.Float: NetworkWriterExtensions.WriteFloat(writer, entry.FloatValue); break; case ConfigValueType.Bool: NetworkWriterExtensions.WriteBool(writer, entry.BoolValue); break; default: NetworkWriterExtensions.WriteString(writer, entry.StringValue); break; } }; Reader.read = delegate(NetworkReader reader) { ConfigEntry result = new ConfigEntry { Key = NetworkReaderExtensions.ReadString(reader), Type = (ConfigValueType)reader.ReadByte() }; switch (result.Type) { case ConfigValueType.String: result.StringValue = NetworkReaderExtensions.ReadString(reader); break; case ConfigValueType.Int: result.IntValue = NetworkReaderExtensions.ReadInt(reader); break; case ConfigValueType.Float: result.FloatValue = NetworkReaderExtensions.ReadFloat(reader); break; case ConfigValueType.Bool: result.BoolValue = NetworkReaderExtensions.ReadBool(reader); break; default: result.StringValue = NetworkReaderExtensions.ReadString(reader); break; } return result; }; Writer.write = delegate(NetworkWriter writer, ConfigScopeUpdateMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.ScopeId); writer.Write(msg.Entry); }; Reader.read = (NetworkReader reader) => new ConfigScopeUpdateMessage { ScopeId = NetworkReaderExtensions.ReadString(reader), Entry = reader.Read() }; Writer.write = delegate(NetworkWriter writer, ConfigScopeFullMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.ScopeId); int num = msg.Entries?.Count ?? 0; NetworkWriterExtensions.WriteInt(writer, num); for (int i = 0; i < num; i++) { writer.Write(msg.Entries[i]); } }; Reader.read = delegate(NetworkReader reader) { ConfigScopeFullMessage result = new ConfigScopeFullMessage { ScopeId = NetworkReaderExtensions.ReadString(reader), Entries = new List() }; int num = NetworkReaderExtensions.ReadInt(reader); for (int i = 0; i < num; i++) { result.Entries.Add(reader.Read()); } return result; }; Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterCommon: registered network message readers/writers (teams + gamemodes + config + raycasts)"); } private static void RegisterClient() { if (_clientRegistered) { Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterClient: already registered"); return; } _clientRegistered = true; Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterClient: registering client handlers"); NetworkClient.RegisterHandler((Action)delegate(TeamAssignMessage msg) { Plugin.Log.LogInfo((object)$"[GamemodeLib] Client received TeamAssignMessage: playerGuid={msg.PlayerGuid} teamId={msg.TeamId}"); TeamManager.Instance?.ApplyTeamMessage(msg); }, true); NetworkClient.RegisterHandler((Action)delegate(TeamDefinitionMessage msg) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received TeamDefinitionMessage: id={0} name='{1}' color={2}", msg.ID, msg.Name ?? "", msg.Color)); TeamManager.Instance?.ApplyTeamDefinitionMessage(msg); }, true); NetworkClient.RegisterHandler((Action)delegate(GamemodeStartMessage msg) { Plugin.Log.LogInfo((object)("[GamemodeLib] Client received GamemodeStartMessage: gamemodeId='" + (msg.GamemodeId ?? "") + "'")); GameModeUtilities.ApplyGamemodeStartMessage(msg); }, true); NetworkClient.RegisterHandler((Action)delegate(GamemodeEndMessage msg) { Plugin.Log.LogInfo((object)("[GamemodeLib] Client received GamemodeEndMessage: gamemodeId='" + (msg.GamemodeId ?? "") + "'")); GameModeUtilities.ApplyGamemodeEndMessage(msg); }, true); NetworkClient.RegisterHandler((Action)delegate(ConfigScopeFullMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received ConfigScopeFullMessage: scopeId='{0}' entries={1}", msg.ScopeId ?? "", msg.Entries?.Count ?? 0)); ConfigSyncManager.Instance?.ApplyFull(msg); }, true); NetworkClient.RegisterHandler((Action)delegate(ConfigScopeUpdateMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received ConfigScopeUpdateMessage: scopeId='{0}' key='{1}' type={2}", msg.ScopeId ?? "", msg.Entry.Key ?? "", (byte)msg.Entry.Type)); ConfigSyncManager.Instance?.ApplyUpdate(msg); }, true); NetworkClient.RegisterHandler((Action)delegate(RaycastResultMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received RaycastResultMessage: purpose='{0}' hasHit={1} root='{2}'", msg.Purpose ?? "", msg.HasHit, msg.ClosestValidRootObjectName ?? "")); RaycastUtility.HandleRaycastResult(msg); }, true); Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterClient: client handlers registered"); } private static void RegisterServer() { if (_serverRegistered) { Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterServer: already registered"); return; } _serverRegistered = true; Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterServer: registering server handlers"); NetworkServer.RegisterHandler((Action)delegate(NetworkConnectionToClient conn, TeamRequestMessage msg) { Plugin.Log.LogInfo((object)$"[GamemodeLib] Server received TeamRequestMessage: connId={conn.connectionId} playerGuid={msg.PlayerGuid}"); TeamManager.Instance?.HandleTeamRequest(conn, msg); }, true); NetworkServer.RegisterHandler((Action)delegate(NetworkConnectionToClient conn, ConfigScopeRequestMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Server received ConfigScopeRequestMessage: connId={0} scopeId='{1}'", conn.connectionId, msg.ScopeId ?? "")); ConfigSyncManager.Instance?.HandleScopeRequest(conn, msg); }, true); NetworkServer.RegisterHandler((Action)delegate(NetworkConnectionToClient conn, RaycastRequestMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Server received RaycastRequestMessage: connId={0} purpose='{1}' maxDistance={2} mask={3}", conn.connectionId, msg.Purpose ?? "", msg.MaxDistance, msg.RaycastMask)); RaycastUtility.HandleRaycastRequest(conn.connectionId, msg); }, true); Plugin.Log.LogInfo((object)"[GamemodeLib] NetworkMessageBootstrap.RegisterServer: server handlers registered"); } [HarmonyPatch(typeof(BNetworkManager), "OnStartClient")] [HarmonyPostfix] public static void OnStartClient_Postfix() { Plugin.Log.LogInfo((object)"[GamemodeLib] BNetworkManager.OnStartClient postfix: registering network messages"); Register(); } [HarmonyPatch(typeof(BNetworkManager), "OnStartServer")] [HarmonyPostfix] public static void OnStartServer_Postfix() { Plugin.Log.LogInfo((object)"[GamemodeLib] BNetworkManager.OnStartServer postfix: registering network messages"); Register(); } [HarmonyPatch(typeof(BNetworkManager), "OnDestroy")] [HarmonyPrefix] public static void OnDestroy_Prefix() { Plugin.Log.LogInfo((object)$"[GamemodeLib] BNetworkManager.OnDestroy prefix: attempting to end current game (serverActive={NetworkServer.active})"); GameModeUtilities.TryEndCurrentGame(NetworkServer.active); } } [BepInPlugin("com.github.glarmer.Gamemode_Lib", "Gamemode_Lib", "0.5.1")] public class Plugin : BaseUnityPlugin { internal readonly Harmony _harmony = new Harmony("com.github.glarmer.Gamemode_Lib"); internal static Plugin Instance; public const string Id = "com.github.glarmer.Gamemode_Lib"; internal static ManualLogSource Log { get; private set; } public static string Name => "Gamemode_Lib"; public static string Version => "0.5.1"; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; GameObject val = new GameObject("GamemodeLib"); val.AddComponent(); Log.LogInfo((object)("Plugin " + Name + " (Version " + Version + ") is patching!")); Log.LogInfo((object)"[GamemodeLib] is running Network patches"); _harmony.PatchAll(typeof(NetworkMessageBootstrap)); Log.LogInfo((object)"[GamemodeLib] is patching Scoreboard"); _harmony.PatchAll(typeof(ScoreboardPatches)); Log.LogInfo((object)"[GamemodeLib] is patching MatchSetupPlayer"); _harmony.PatchAll(typeof(MatchSetupPlayerPatches)); Log.LogInfo((object)"[GamemodeLib] is patching CourseManager"); _harmony.PatchAll(typeof(CourseManagerPatches)); Log.LogInfo((object)"[GamemodeLib] is patching NameTagUi"); _harmony.PatchAll(typeof(NameTagUiPatches)); Log.LogInfo((object)"[GamemodeLib] is patching GameManager"); _harmony.PatchAll(typeof(GameManagerPatches)); Log.LogInfo((object)"[GamemodeLib] is patching MatchSetup"); _harmony.PatchAll(typeof(MatchSetupMenuPatches)); Log.LogInfo((object)"[GamemodeLib] is patching PlayerInfo"); _harmony.PatchAll(typeof(PlayerInfoPatches)); _harmony.PatchAll(typeof(TeeOffCountdownPatches)); Log.LogInfo((object)"[GamemodeLib] is finished patching."); SceneEvents.Init(); SceneEvents.OnReturnToLobby += OnReturnToLobby; PlayerEvents.Init(); Log.LogInfo((object)"[GamemodeLib] Initialized."); } private void OnReturnToLobby(Scene hole, Scene lobby) { if (GameModeUtilities.CurrentGamemodeId != null) { GameModeUtilities.TryEndCurrentGame(broadcastToClients: true); } GameModeUtilities.ReinitializeGameState(); } private void OnDestroy() { SceneEvents.OnReturnToLobby -= OnReturnToLobby; SceneEvents.Shutdown(); _harmony.UnpatchSelf(); } } public static class RaycastUtility { public readonly struct RaycastCompletedEventArgs { public readonly string Purpose; public readonly int RequestingConnectionId; public readonly ulong RequestingClientGuid; public readonly Vector3 Origin; public readonly Vector3 Direction; public readonly float MaxDistance; public readonly int RaycastMask; public readonly bool HasHit; public readonly RaycastHit Hit; public readonly GameObject ClosestValidRootObject; public RaycastCompletedEventArgs(string purpose, int requestingConnectionId, ulong requestingClientGuid, Vector3 origin, Vector3 direction, float maxDistance, int raycastMask, bool hasHit, RaycastHit hit, GameObject closestValidRootObject) { //IL_0016: 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_001e: 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_003e: 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) Purpose = purpose; RequestingConnectionId = requestingConnectionId; RequestingClientGuid = requestingClientGuid; Origin = origin; Direction = direction; MaxDistance = maxDistance; RaycastMask = raycastMask; HasHit = hasHit; Hit = hit; ClosestValidRootObject = closestValidRootObject; } } public readonly struct RaycastResultReceivedEventArgs { public readonly string Purpose; public readonly ulong RequestingClientGuid; public readonly Vector3 Origin; public readonly Vector3 Direction; public readonly float MaxDistance; public readonly int RaycastMask; public readonly bool HasHit; public readonly Vector3 HitPoint; public readonly Vector3 HitNormal; public readonly float HitDistance; public readonly string HitObjectName; public readonly string ClosestValidRootObjectName; public RaycastResultReceivedEventArgs(string purpose, ulong requestingClientGuid, Vector3 origin, Vector3 direction, float maxDistance, int raycastMask, bool hasHit, Vector3 hitPoint, Vector3 hitNormal, float hitDistance, string hitObjectName, string closestValidRootObjectName) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) Purpose = purpose; RequestingClientGuid = requestingClientGuid; Origin = origin; Direction = direction; MaxDistance = maxDistance; RaycastMask = raycastMask; HasHit = hasHit; HitPoint = hitPoint; HitNormal = hitNormal; HitDistance = hitDistance; HitObjectName = hitObjectName; ClosestValidRootObjectName = closestValidRootObjectName; } } public static event Action RaycastCompleted; public static event Action RaycastResultReceived; public static GameObject GetClosestValidObjectFromMainCameraCenter(float maxDistance = 100f, LayerMask raycastMask = default(LayerMask)) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return null; } return GetClosestValidObject(((Component)main).transform.position, ((Component)main).transform.forward, maxDistance, raycastMask); } public static GameObject GetClosestValidObject(Vector3 origin, Vector3 direction, float maxDistance = 100f, LayerMask raycastMask = default(LayerMask)) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0031: 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) if (LayerMask.op_Implicit(raycastMask) == 0) { raycastMask = LayerMask.op_Implicit(-1); } if (((Vector3)(ref direction)).sqrMagnitude <= 1E-06f) { return null; } Ray val = default(Ray); ((Ray)(ref val))..ctor(origin, ((Vector3)(ref direction)).normalized); RaycastHit[] array = Physics.RaycastAll(val, maxDistance, LayerMask.op_Implicit(raycastMask), (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val2 = array2[num]; GameObject gameObject = ((Component)((RaycastHit)(ref val2)).collider).gameObject; if (!ShouldIgnore(gameObject)) { return GetHighestParent(gameObject); } } return null; } public static void RequestRaycastOnHost(string purpose, ulong guid, Vector3 origin, Vector3 direction, float maxDistance = 100f, LayerMask raycastMask = default(LayerMask)) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references) if (NetworkClient.active) { if (NetworkServer.active) { HandleRaycastRequest(-1, new RaycastRequestMessage { Purpose = purpose, Guid = guid, Origin = origin, Direction = direction, MaxDistance = maxDistance, RaycastMask = ((LayerMask.op_Implicit(raycastMask) == 0) ? (-1) : ((LayerMask)(ref raycastMask)).value) }); } else { NetworkMessageBootstrap.Register(); NetworkClient.Send(new RaycastRequestMessage { Purpose = purpose, Guid = guid, Origin = origin, Direction = direction, MaxDistance = maxDistance, RaycastMask = ((LayerMask.op_Implicit(raycastMask) == 0) ? (-1) : ((LayerMask)(ref raycastMask)).value) }, 0); } } } internal static void HandleRaycastRequest(int requestingConnectionId, RaycastRequestMessage msg) { //IL_001b: 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_0025: 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_0053: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_0119: 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) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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_019a: 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) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: 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) if (!NetworkServer.active) { return; } int num = ((msg.RaycastMask == 0) ? (-1) : msg.RaycastMask); LayerMask val = LayerMask.op_Implicit(num); bool flag = false; RaycastHit hit = default(RaycastHit); GameObject val2 = null; if (((Vector3)(ref msg.Direction)).sqrMagnitude > 1E-06f) { Ray val3 = default(Ray); ((Ray)(ref val3))..ctor(msg.Origin, ((Vector3)(ref msg.Direction)).normalized); RaycastHit[] array = Physics.RaycastAll(val3, msg.MaxDistance, LayerMask.op_Implicit(val), (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num2 = 0; num2 < array2.Length; num2++) { RaycastHit val4 = array2[num2]; GameObject gameObject = ((Component)((RaycastHit)(ref val4)).collider).gameObject; if (!ShouldIgnore(gameObject)) { flag = true; hit = val4; val2 = GetHighestParent(gameObject); break; } } } if (!((Object)(object)val2 == (Object)null)) { RaycastUtility.RaycastCompleted?.Invoke(new RaycastCompletedEventArgs(msg.Purpose, requestingConnectionId, msg.Guid, msg.Origin, msg.Direction, msg.MaxDistance, num, flag, hit, val2)); NetworkMessageBootstrap.Register(); NetworkServer.SendToAll(new RaycastResultMessage { Purpose = (msg.Purpose ?? string.Empty), Guid = msg.Guid, Origin = msg.Origin, Direction = msg.Direction, MaxDistance = msg.MaxDistance, RaycastMask = num, HasHit = flag, HitPoint = (Vector3)(flag ? ((RaycastHit)(ref hit)).point : default(Vector3)), HitNormal = (Vector3)(flag ? ((RaycastHit)(ref hit)).normal : default(Vector3)), HitDistance = (flag ? ((RaycastHit)(ref hit)).distance : 0f), HitObjectName = (flag ? ((Object)((Component)((RaycastHit)(ref hit)).collider).gameObject).name : string.Empty), ClosestValidRootObjectName = (((Object)val2).name ?? string.Empty) }, 0, false); } } internal static void HandleRaycastResult(RaycastResultMessage msg) { //IL_0017: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) RaycastUtility.RaycastResultReceived?.Invoke(new RaycastResultReceivedEventArgs(msg.Purpose, msg.Guid, msg.Origin, msg.Direction, msg.MaxDistance, msg.RaycastMask, msg.HasHit, msg.HitPoint, msg.HitNormal, msg.HitDistance, msg.HitObjectName, msg.ClosestValidRootObjectName)); } private static bool ShouldIgnore(GameObject obj) { Transform val = obj.transform; while ((Object)(object)val != (Object)null) { if (((Object)val).name == "Terrain") { return true; } if ((Object)(object)((Component)val).GetComponent() != (Object)null) { return true; } val = val.parent; } return false; } private static GameObject GetHighestParent(GameObject obj) { Transform val = obj.transform; while ((Object)(object)val.parent != (Object)null) { val = val.parent; } return ((Component)val).gameObject; } } } namespace Gamemode_Lib.Patches { public class CourseManagerPatches { [HarmonyPatch(typeof(CourseManager), "EndCourse")] [HarmonyPrefix] public static void EndCourse_Prefix() { Plugin.Log.LogInfo((object)$"[GamemodeLib] CourseManager.EndCourse prefix: TryEndCurrentGame(broadcastToClients=true) serverActive={NetworkServer.active}"); GameModeUtilities.TryEndCurrentGame(broadcastToClients: true); } } public class GameManagerPatches { [HarmonyPatch(typeof(GameManager), "Awake")] [HarmonyPostfix] public static void Awake_Postfix(GameManager __instance) { ((Component)__instance).gameObject.AddComponent(); } } public class MatchSetupMenuPatches { private static readonly Dictionary> DropdownMappings = new Dictionary>(); private static TMP_Dropdown? _tmpDropdown; private static IGamemode? _gameMode; [HarmonyPatch(typeof(MatchSetupMenu), "SetEnabled")] [HarmonyPostfix] public static void SetEnabled_Postfix(MatchSetupMenu __instance) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown if ((Object)(object)_tmpDropdown == (Object)null) { _tmpDropdown = ((IEnumerable)Object.FindObjectsOfType(true)).FirstOrDefault((Func)((TMP_Dropdown dropdown) => dropdown.options != null && dropdown.options.Any((OptionData o) => o.text == "Free-for-all"))); if ((Object)(object)_tmpDropdown == (Object)null) { Plugin.Log.LogError((object)"[GamemodeLib] Could not find TMP_Dropdown containing 'Free-for-all'"); return; } } if (DropdownMappings.ContainsKey(_tmpDropdown)) { return; } Dictionary dictionary = new Dictionary(); int num = _tmpDropdown.options.Count; foreach (KeyValuePair mode in GameModeUtilities.Modes) { string key = mode.Key; IGamemode value = mode.Value; _tmpDropdown.options.Add(new OptionData(value.Name)); dictionary[num] = key; num++; } _tmpDropdown.RefreshShownValue(); DropdownMappings[_tmpDropdown] = dictionary; ((UnityEvent)(object)_tmpDropdown.onValueChanged).AddListener((UnityAction)delegate(int index) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)("[GamemodeLib] Selected gamemode: " + _tmpDropdown.options[index].text + ")")); _gameMode = null; if (DropdownMappings[_tmpDropdown].TryGetValue(index, out string value2)) { IGamemode gamemode = (_gameMode = GameModeUtilities.Modes[value2]); Plugin.Log.LogInfo((object)("[GamemodeLib] " + gamemode.Name + " is using GamemodeLib. It's ID is... " + gamemode.GameModeId)); if (NetworkServer.active) { TeamManager.Instance.ResetTeams(); TeamManager.Instance.ClearTeamDefinitions(); if (_gameMode.IsTeamBased) { __instance.gameMode = (GameMode)0; __instance.OnGameModeChanged((GameMode)1, (GameMode)0); TeamManager.Instance.CreateAndAssignTeams(_gameMode.TeamCount); } else { __instance.gameMode = (GameMode)0; __instance.OnGameModeChanged((GameMode)1, (GameMode)0); } } } }); Plugin.Log.LogInfo((object)"[GamemodeLib] Gamemodes injected into dropdown"); } [HarmonyPatch(typeof(MatchSetupMenu), "StartOrCancelMatch")] [HarmonyPrefix] public static bool StartOrCancelMatch_Prefix(MatchSetupMenu __instance) { if ((Object)(object)_tmpDropdown == (Object)null) { return true; } if (_gameMode == null) { return true; } if (_gameMode.CanStart(__instance.maxPlayers)) { if (StartGame()) { StopAutoNextHole.HideCursor(); return true; } } else { Plugin.Log.LogError((object)"[GamemodeLib] Invalid choices, not starting gamemode."); } return false; } private static bool StartGame() { Plugin.Log.LogInfo((object)"[GamemodeLib] Starting gamemode."); if ((Object)(object)TeamManager.Instance != (Object)null) { TeamManager.Instance.AssignUnAssignedPlayersToTeams(); TeamManager.Instance.SaveCurrentTeams(); TeamManager.Instance.TryRefreshLocalPlayerTeam(); if ((Object)(object)TeamManager.Instance.LocalPlayerTeam == (Object)null) { Plugin.Log.LogWarning((object)"[GamemodeLib] LocalPlayerTeam is null immediately before OnGameStart()"); } } GameModeUtilities.CurrentGamemodeId = _gameMode.GameModeId; GameModeUtilities.GameEnded = false; _gameMode.OnGameStart(); if (NetworkServer.active) { NetworkMessageBootstrap.Register(); ConfigSyncManager.Instance?.BroadcastScopeToClients(_gameMode.GameModeId); NetworkServer.SendToAll(new GamemodeStartMessage { GamemodeId = _gameMode.GameModeId }, 0, false); } if (_gameMode.IsNormalStartProcedure) { return true; } Plugin.Log.LogInfo((object)"[GamemodeLib] Custom gamemode is chosen, cancelling default start procedure."); return false; } [HarmonyPatch(typeof(MatchSetupMenu), "StartOrCancelMatch")] [HarmonyPostfix] public static void StartOrCancelMatch_Postfix(MatchSetupMenu __instance) { TeamManager.Instance.ReloadSavedTeams(); } } public class MatchSetupPlayerPatches { private const string SwapButtonName = "SwapTeamButton"; [HarmonyPatch(typeof(MatchSetupPlayerEntry), "Update")] [HarmonyPostfix] public static void Update_Postfix(MatchSetupPlayerEntry __instance) { UpdateBackground(__instance); } [HarmonyPatch(typeof(MatchSetupPlayerEntry), "Awake")] [HarmonyPostfix] public static void Awake_Postfix(MatchSetupPlayerEntry __instance) { AddSwapButton(__instance); } private static void UpdateBackground(MatchSetupPlayerEntry playerUI) { //IL_00ce: 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_0116: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)TeamManager.Instance == (Object)null) { return; } ulong guid = playerUI.Guid; PlayerTeam playerTeam = null; foreach (PlayerTeam player in TeamManager.Instance.Players) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player.playerInfo == (Object)null) && player.playerInfo.PlayerId.guid == guid) { playerTeam = player; break; } } if ((Object)(object)playerTeam == (Object)null || !TeamManager.Instance.TryGetTeam(playerTeam.teamId, out TeamData team)) { return; } Transform val = ((Component)playerUI).transform.Find("Background"); if ((Object)(object)val == (Object)null) { return; } Image component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { return; } ((Graphic)component).color = team.Color; Transform val2 = ((Component)playerUI).transform.Find("Portrait"); if (!((Object)(object)val2 == (Object)null)) { Image component2 = ((Component)val2).GetComponent(); if (!((Object)(object)component2 == (Object)null)) { ((Graphic)component2).color = team.Color * 0.7f; } } } private static void AddSwapButton(MatchSetupPlayerEntry ui) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Expected O, but got Unknown Transform val = ((Component)ui).transform.Find("Info").Find("Buttons"); if ((Object)(object)val == (Object)null || (Object)(object)val.Find("SwapTeamButton") != (Object)null) { return; } Button kickButton = ui.kickButton; if ((Object)(object)kickButton == (Object)null) { return; } GameObject val2 = Object.Instantiate(((Component)kickButton).gameObject, val); ((Object)val2).name = "SwapTeamButton"; Button component = val2.GetComponent