Decompiled source of Gamemode Lib v0.1.0
com.github.glarmer.Gamemode_Lib.dll
Decompiled 3 weeks 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.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [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("Debug")] [assembly: AssemblyFileVersion("0.5.1.0")] [assembly: AssemblyInformationalVersion("0.5.1+852d639c41ee959ea823f8321301795369f5d33c")] [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] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.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")] [Microsoft.CodeAnalysis.Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace Gamemode_Lib { public static class GameModeUtilities { public static Dictionary<string, IGamemode> Modes { get; } = new Dictionary<string, IGamemode>(); 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 ?? "<null>"))); 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); if (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 ?? "<null>", message.GamemodeId ?? "<null>"))); 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 ?? "<null>"))); 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 ?? "<null>", message.GamemodeId ?? "<null>"))); 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 ?? "<null>"))); 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 ?? "<null>"))); 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(); GamemodeEndMessage gamemodeEndMessage = default(GamemodeEndMessage); gamemodeEndMessage.GamemodeId = currentGamemodeId; NetworkServer.SendToAll<GamemodeEndMessage>(gamemodeEndMessage, 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<TeamAssignMessage>.write = delegate(NetworkWriter writer, TeamAssignMessage msg) { NetworkWriterExtensions.WriteULong(writer, msg.PlayerGuid); NetworkWriterExtensions.WriteInt(writer, msg.TeamId); }; Reader<TeamAssignMessage>.read = delegate(NetworkReader reader) { TeamAssignMessage result11 = default(TeamAssignMessage); result11.PlayerGuid = NetworkReaderExtensions.ReadULong(reader); result11.TeamId = NetworkReaderExtensions.ReadInt(reader); return result11; }; Writer<TeamRequestMessage>.write = delegate(NetworkWriter writer, TeamRequestMessage msg) { NetworkWriterExtensions.WriteULong(writer, msg.PlayerGuid); }; Reader<TeamRequestMessage>.read = delegate(NetworkReader reader) { TeamRequestMessage result10 = default(TeamRequestMessage); result10.PlayerGuid = NetworkReaderExtensions.ReadULong(reader); return result10; }; Writer<TeamDefinitionMessage>.write = delegate(NetworkWriter writer, TeamDefinitionMessage msg) { //IL_0010: 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<TeamDefinitionMessage>.read = delegate(NetworkReader reader) { //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) TeamDefinitionMessage result9 = default(TeamDefinitionMessage); result9.ID = NetworkReaderExtensions.ReadInt(reader); result9.Color = NetworkReaderExtensions.ReadColor(reader); result9.Name = NetworkReaderExtensions.ReadString(reader); return result9; }; Writer<GamemodeStartMessage>.write = delegate(NetworkWriter writer, GamemodeStartMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.GamemodeId); }; Reader<GamemodeStartMessage>.read = delegate(NetworkReader reader) { GamemodeStartMessage result8 = default(GamemodeStartMessage); result8.GamemodeId = NetworkReaderExtensions.ReadString(reader); return result8; }; Writer<GamemodeEndMessage>.write = delegate(NetworkWriter writer, GamemodeEndMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.GamemodeId); }; Reader<GamemodeEndMessage>.read = delegate(NetworkReader reader) { GamemodeEndMessage result7 = default(GamemodeEndMessage); result7.GamemodeId = NetworkReaderExtensions.ReadString(reader); return result7; }; Writer<RaycastRequestMessage>.write = delegate(NetworkWriter writer, RaycastRequestMessage msg) { //IL_001d: 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) 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<RaycastRequestMessage>.read = delegate(NetworkReader reader) { //IL_0025: 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_0032: 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) RaycastRequestMessage result6 = default(RaycastRequestMessage); result6.Purpose = NetworkReaderExtensions.ReadString(reader); result6.Guid = NetworkReaderExtensions.ReadULong(reader); result6.Origin = NetworkReaderExtensions.ReadVector3(reader); result6.Direction = NetworkReaderExtensions.ReadVector3(reader); result6.MaxDistance = NetworkReaderExtensions.ReadFloat(reader); result6.RaycastMask = NetworkReaderExtensions.ReadInt(reader); return result6; }; Writer<RaycastResultMessage>.write = delegate(NetworkWriter writer, RaycastResultMessage msg) { //IL_001d: 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_005e: 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) 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<RaycastResultMessage>.read = delegate(NetworkReader reader) { //IL_0025: 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_0032: 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_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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) RaycastResultMessage result5 = default(RaycastResultMessage); result5.Purpose = NetworkReaderExtensions.ReadString(reader); result5.Guid = NetworkReaderExtensions.ReadULong(reader); result5.Origin = NetworkReaderExtensions.ReadVector3(reader); result5.Direction = NetworkReaderExtensions.ReadVector3(reader); result5.MaxDistance = NetworkReaderExtensions.ReadFloat(reader); result5.RaycastMask = NetworkReaderExtensions.ReadInt(reader); result5.HasHit = NetworkReaderExtensions.ReadBool(reader); result5.HitPoint = NetworkReaderExtensions.ReadVector3(reader); result5.HitNormal = NetworkReaderExtensions.ReadVector3(reader); result5.HitDistance = NetworkReaderExtensions.ReadFloat(reader); result5.HitObjectName = NetworkReaderExtensions.ReadString(reader); result5.ClosestValidRootObjectName = NetworkReaderExtensions.ReadString(reader); return result5; }; Writer<ConfigScopeRequestMessage>.write = delegate(NetworkWriter writer, ConfigScopeRequestMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.ScopeId); }; Reader<ConfigScopeRequestMessage>.read = delegate(NetworkReader reader) { ConfigScopeRequestMessage result4 = default(ConfigScopeRequestMessage); result4.ScopeId = NetworkReaderExtensions.ReadString(reader); return result4; }; Writer<ConfigEntry>.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<ConfigEntry>.read = delegate(NetworkReader reader) { ConfigEntry configEntry = default(ConfigEntry); configEntry.Key = NetworkReaderExtensions.ReadString(reader); configEntry.Type = (ConfigValueType)reader.ReadByte(); ConfigEntry result3 = configEntry; switch (result3.Type) { case ConfigValueType.String: result3.StringValue = NetworkReaderExtensions.ReadString(reader); break; case ConfigValueType.Int: result3.IntValue = NetworkReaderExtensions.ReadInt(reader); break; case ConfigValueType.Float: result3.FloatValue = NetworkReaderExtensions.ReadFloat(reader); break; case ConfigValueType.Bool: result3.BoolValue = NetworkReaderExtensions.ReadBool(reader); break; default: result3.StringValue = NetworkReaderExtensions.ReadString(reader); break; } return result3; }; Writer<ConfigScopeUpdateMessage>.write = delegate(NetworkWriter writer, ConfigScopeUpdateMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.ScopeId); writer.Write<ConfigEntry>(msg.Entry); }; Reader<ConfigScopeUpdateMessage>.read = delegate(NetworkReader reader) { ConfigScopeUpdateMessage result2 = default(ConfigScopeUpdateMessage); result2.ScopeId = NetworkReaderExtensions.ReadString(reader); result2.Entry = reader.Read<ConfigEntry>(); return result2; }; Writer<ConfigScopeFullMessage>.write = delegate(NetworkWriter writer, ConfigScopeFullMessage msg) { NetworkWriterExtensions.WriteString(writer, msg.ScopeId); int num2 = msg.Entries?.Count ?? 0; NetworkWriterExtensions.WriteInt(writer, num2); for (int j = 0; j < num2; j++) { writer.Write<ConfigEntry>(msg.Entries[j]); } }; Reader<ConfigScopeFullMessage>.read = delegate(NetworkReader reader) { ConfigScopeFullMessage configScopeFullMessage = default(ConfigScopeFullMessage); configScopeFullMessage.ScopeId = NetworkReaderExtensions.ReadString(reader); configScopeFullMessage.Entries = new List<ConfigEntry>(); ConfigScopeFullMessage result = configScopeFullMessage; int num = NetworkReaderExtensions.ReadInt(reader); for (int i = 0; i < num; i++) { result.Entries.Add(reader.Read<ConfigEntry>()); } 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<TeamAssignMessage>((Action<TeamAssignMessage>)delegate(TeamAssignMessage msg) { Plugin.Log.LogInfo((object)$"[GamemodeLib] Client received TeamAssignMessage: playerGuid={msg.PlayerGuid} teamId={msg.TeamId}"); TeamManager.Instance?.ApplyTeamMessage(msg); }, true); NetworkClient.RegisterHandler<TeamDefinitionMessage>((Action<TeamDefinitionMessage>)delegate(TeamDefinitionMessage msg) { //IL_0026: 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 ?? "<null>", msg.Color)); TeamManager.Instance?.ApplyTeamDefinitionMessage(msg); }, true); NetworkClient.RegisterHandler<GamemodeStartMessage>((Action<GamemodeStartMessage>)delegate(GamemodeStartMessage msg) { Plugin.Log.LogInfo((object)("[GamemodeLib] Client received GamemodeStartMessage: gamemodeId='" + (msg.GamemodeId ?? "<null>") + "'")); GameModeUtilities.ApplyGamemodeStartMessage(msg); }, true); NetworkClient.RegisterHandler<GamemodeEndMessage>((Action<GamemodeEndMessage>)delegate(GamemodeEndMessage msg) { Plugin.Log.LogInfo((object)("[GamemodeLib] Client received GamemodeEndMessage: gamemodeId='" + (msg.GamemodeId ?? "<null>") + "'")); GameModeUtilities.ApplyGamemodeEndMessage(msg); }, true); NetworkClient.RegisterHandler<ConfigScopeFullMessage>((Action<ConfigScopeFullMessage>)delegate(ConfigScopeFullMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received ConfigScopeFullMessage: scopeId='{0}' entries={1}", msg.ScopeId ?? "<null>", msg.Entries?.Count ?? 0)); ConfigSyncManager.Instance?.ApplyFull(msg); }, true); NetworkClient.RegisterHandler<ConfigScopeUpdateMessage>((Action<ConfigScopeUpdateMessage>)delegate(ConfigScopeUpdateMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received ConfigScopeUpdateMessage: scopeId='{0}' key='{1}' type={2}", msg.ScopeId ?? "<null>", msg.Entry.Key ?? "<null>", (byte)msg.Entry.Type)); ConfigSyncManager.Instance?.ApplyUpdate(msg); }, true); NetworkClient.RegisterHandler<RaycastResultMessage>((Action<RaycastResultMessage>)delegate(RaycastResultMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Client received RaycastResultMessage: purpose='{0}' hasHit={1} root='{2}'", msg.Purpose ?? "<null>", msg.HasHit, msg.ClosestValidRootObjectName ?? "<null>")); 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<TeamRequestMessage>((Action<NetworkConnectionToClient, TeamRequestMessage>)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<ConfigScopeRequestMessage>((Action<NetworkConnectionToClient, ConfigScopeRequestMessage>)delegate(NetworkConnectionToClient conn, ConfigScopeRequestMessage msg) { Plugin.Log.LogInfo((object)string.Format("[GamemodeLib] Server received ConfigScopeRequestMessage: connId={0} scopeId='{1}'", conn.connectionId, msg.ScopeId ?? "<null>")); ConfigSyncManager.Instance?.HandleScopeRequest(conn, msg); }, true); NetworkServer.RegisterHandler<RaycastRequestMessage>((Action<NetworkConnectionToClient, RaycastRequestMessage>)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 ?? "<null>", 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; GameObject val = new GameObject("GamemodeLib"); val.AddComponent<ConfigSyncManager>(); 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<RaycastCompletedEventArgs> RaycastCompleted; public static event Action<RaycastResultReceivedEventArgs> RaycastResultReceived; public static GameObject GetClosestValidObjectFromMainCameraCenter(float maxDistance = 100f, LayerMask raycastMask = default(LayerMask)) { //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_002d: 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0038: 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_0044: 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_0089: 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 i = 0; i < array2.Length; i++) { RaycastHit val2 = array2[i]; 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_009a: 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) //IL_0037: 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_003f: 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) 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(); RaycastRequestMessage raycastRequestMessage = default(RaycastRequestMessage); raycastRequestMessage.Purpose = purpose; raycastRequestMessage.Guid = guid; raycastRequestMessage.Origin = origin; raycastRequestMessage.Direction = direction; raycastRequestMessage.MaxDistance = maxDistance; raycastRequestMessage.RaycastMask = ((LayerMask.op_Implicit(raycastMask) == 0) ? (-1) : ((LayerMask)(ref raycastMask)).value); NetworkClient.Send<RaycastRequestMessage>(raycastRequestMessage, 0); } } } internal static void HandleRaycastRequest(int requestingConnectionId, RaycastRequestMessage msg) { //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) //IL_005a: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: 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 i = 0; i < array2.Length; i++) { RaycastHit val4 = array2[i]; 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(); RaycastResultMessage raycastResultMessage = default(RaycastResultMessage); raycastResultMessage.Purpose = msg.Purpose ?? string.Empty; raycastResultMessage.Guid = msg.Guid; raycastResultMessage.Origin = msg.Origin; raycastResultMessage.Direction = msg.Direction; raycastResultMessage.MaxDistance = msg.MaxDistance; raycastResultMessage.RaycastMask = num; raycastResultMessage.HasHit = flag; raycastResultMessage.HitPoint = (Vector3)(flag ? ((RaycastHit)(ref hit)).point : default(Vector3)); raycastResultMessage.HitNormal = (Vector3)(flag ? ((RaycastHit)(ref hit)).normal : default(Vector3)); raycastResultMessage.HitDistance = (flag ? ((RaycastHit)(ref hit)).distance : 0f); raycastResultMessage.HitObjectName = (flag ? ((Object)((Component)((RaycastHit)(ref hit)).collider).gameObject).name : string.Empty); raycastResultMessage.ClosestValidRootObjectName = ((Object)val2).name ?? string.Empty; NetworkServer.SendToAll<RaycastResultMessage>(raycastResultMessage, 0, false); } } internal static void HandleRaycastResult(RaycastResultMessage msg) { //IL_0019: 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_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) 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<PlayerInfo>() != (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<TeamManager>(); } } public class MatchSetupMenuPatches { private static readonly Dictionary<TMP_Dropdown, Dictionary<int, string>> DropdownMappings = new Dictionary<TMP_Dropdown, Dictionary<int, string>>(); private static TMP_Dropdown? _tmpDropdown; private static IGamemode? _gameMode; [HarmonyPatch(typeof(MatchSetupMenu), "SetEnabled")] [HarmonyPostfix] public static void SetEnabled_Postfix(MatchSetupMenu __instance) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown if ((Object)(object)_tmpDropdown == (Object)null) { _tmpDropdown = ((IEnumerable<TMP_Dropdown>)Object.FindObjectsOfType<TMP_Dropdown>(true)).FirstOrDefault((Func<TMP_Dropdown, bool>)((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<int, string> dictionary = new Dictionary<int, string>(); int num = _tmpDropdown.options.Count; foreach (KeyValuePair<string, IGamemode> 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<int>)(object)_tmpDropdown.onValueChanged).AddListener((UnityAction<int>)delegate(int index) { 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) { TeamManager.Instance.CreateAndAssignTeams(_gameMode.TeamCount); } } } }); 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); GamemodeStartMessage gamemodeStartMessage = default(GamemodeStartMessage); gamemodeStartMessage.GamemodeId = _gameMode.GameModeId; NetworkServer.SendToAll<GamemodeStartMessage>(gamemodeStartMessage, 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(MatchSetupPlayer), "Update")] [HarmonyPostfix] public static void Update_Postfix(MatchSetupPlayer __instance) { UpdateBackground(__instance); } [HarmonyPatch(typeof(MatchSetupPlayer), "Awake")] [HarmonyPostfix] public static void Awake_Postfix(MatchSetupPlayer __instance) { AddSwapButton(__instance); } private static void UpdateBackground(MatchSetupPlayer playerUI) { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0151: 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) 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) { continue; } 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<Image>(); 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<Image>(); if (!((Object)(object)component2 == (Object)null)) { ((Graphic)component2).color = team.Color * 0.7f; } } } private static void AddSwapButton(MatchSetupPlayer ui) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Expected O, but got Unknown MatchSetupPlayer ui2 = ui; Transform val = ((Component)ui2).transform.Find("Info").Find("Buttons"); if ((Object)(object)val == (Object)null || (Object)(object)val.Find("SwapTeamButton") != (Object)null) { return; } Button kickButton = ui2.kickButton; if ((Object)(object)kickButton == (Object)null) { return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)kickButton).gameObject, val); ((Object)val2).name = "SwapTeamButton"; Button component = val2.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { return; } foreach (Transform item in val2.transform) { Transform val3 = item; Object.Destroy((Object)(object)((Component)val3).gameObject); } GameObject val4 = new GameObject("Label", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val2.transform, false); RectTransform component2 = val4.GetComponent<RectTransform>(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; TextMeshProUGUI val5 = val4.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val5).text = "<->"; ((TMP_Text)val5).alignment = (TextAlignmentOptions)514; ((TMP_Text)val5).fontSize = 24f; ((TMP_Text)val5).enableAutoSizing = true; ((TMP_Text)val5).fontSizeMin = 12f; ((TMP_Text)val5).fontSizeMax = 28f; ((Graphic)val5).raycastTarget = false; ((TMP_Text)val5).font = TMP_Settings.defaultFontAsset; Image component3 = val2.GetComponent<Image>(); if ((Object)(object)component3 != (Object)null) { component3.sprite = null; ((Graphic)component3).color = new Color(0.25f, 0.25f, 0.25f, 0.9f); } LayoutElement val6 = val2.GetComponent<LayoutElement>(); if ((Object)(object)val6 == (Object)null) { val6 = val2.AddComponent<LayoutElement>(); } val6.preferredWidth = 60f; val6.preferredHeight = 40f; ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { OnSwapClicked(ui2); }); val2.SetActive(NetworkServer.active && NetworkClient.active); } private static void OnSwapClicked(MatchSetupPlayer ui) { if (!NetworkServer.active) { return; } TeamManager instance = TeamManager.Instance; if ((Object)(object)instance == (Object)null) { return; } ulong guid = ui.Guid; foreach (PlayerTeam player in instance.Players) { if ((Object)(object)player == (Object)null || (Object)(object)player.playerInfo == (Object)null || player.playerInfo.PlayerId.guid != guid) { continue; } int nextTeam = GetNextTeam(player.teamId, instance); instance.SetTeam(player, nextTeam); break; } } private static int GetNextTeam(int current, TeamManager manager) { if (manager.Teams.Count == 0) { return -1; } List<int> list = manager.Teams.Keys.OrderBy((int x) => x).ToList(); int num = list.IndexOf(current); if (num == -1 || num + 1 >= list.Count) { return list[0]; } return list[num + 1]; } } public class NameTagUiPatches { [HarmonyPatch(typeof(NameTagUi), "LateUpdate")] [HarmonyPostfix] public static void LateUpdate_Postfix(NameTagUi __instance) { //IL_0029: 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_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_0125: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SingletonNetworkBehaviour<CourseManager>.Instance != (Object)null && SingletonNetworkBehaviour<CourseManager>.Instance.currentHoleCourseIndex == -1) { ((Graphic)__instance.tag).color = Color.white; } if (!((Object)(object)TeamManager.Instance == (Object)null) && (GameModeUtilities.CurrentGamemodeId == null || GameModeUtilities.Modes[GameModeUtilities.CurrentGamemodeId].IsTeamBased) && TeamManager.Instance.SavedTeamIdByGuid != null && TeamManager.Instance.SavedTeamIdByGuid.Count != 0 && TeamManager.Instance.Teams != null && TeamManager.Instance.Teams.Count != 0) { PlayerInfo playerInfo = __instance.playerInfo; if (!((Object)(object)playerInfo == (Object)null)) { int num = TeamManager.Instance.SavedTeamIdByGuid[playerInfo.PlayerId.guid]; Color color = ((num == -1) ? Color.white : TeamManager.Instance.Teams[num].Color); ((Graphic)__instance.tag).color = color; } } } } public class PlayerInfoPatches { [HarmonyPatch(typeof(PlayerInfo), "Start")] [HarmonyPostfix] public static void Start_Postfix(PlayerInfo __instance) { TeamManager instance = TeamManager.Instance; if (!((Object)(object)instance == (Object)null)) { instance.EnsurePlayerTeam(__instance); instance.RequestTeamFromHost(__instance); } } [HarmonyPatch(typeof(PlayerInfo), "ServerInitializeAsParticipant")] [HarmonyPostfix] public static void ServerInitializeAsParticipant_Postfix(PlayerInfo __instance) { Plugin.Log.LogInfo((object)"ServerInitializeAsParticipant_Postfix"); TeamManager instance = TeamManager.Instance; Plugin.Log.LogInfo((object)"ServerInitializeAsParticipant_Postfix2"); if (!((Object)(object)instance == (Object)null)) { Plugin.Log.LogInfo((object)"ServerInitializeAsParticipant_Postfix3"); instance.EnsurePlayerTeam(__instance); Plugin.Log.LogInfo((object)"ServerInitializeAsParticipant_Postfix4"); instance.TryApplySavedTeam(__instance); Plugin.Log.LogInfo((object)"ServerInitializeAsParticipant_Postfix5"); } } } public class ScoreboardPatches { private class ColorCache { public Color background; public Color statusBackground; public Color infoBackground; public Color statsBackground; public Color stripes; } private static readonly Dictionary<ScoreboardEntry, ColorCache> OriginalColors = new Dictionary<ScoreboardEntry, ColorCache>(); [HarmonyPatch(typeof(ScoreboardEntry), "PopulateWith")] [HarmonyPostfix] public static void PopulateWith_Postfix(ScoreboardEntry __instance, PlayerState playerState) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) CacheOriginalColors(__instance); ApplyTeamColors(__instance, playerState); } private static void CacheOriginalColors(ScoreboardEntry entry) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_003a: 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_004b: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!OriginalColors.ContainsKey(entry)) { OriginalColors[entry] = new ColorCache { background = ((Graphic)entry.background).color, statusBackground = ((Graphic)entry.statusBackground).color, infoBackground = ((Graphic)entry.infoBackground).color, statsBackground = ((Graphic)entry.statsBackground).color, stripes = ((Graphic)entry.stripes).color }; } } private static void ApplyTeamColors(ScoreboardEntry entry, PlayerState state) { //IL_0003: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) PlayerInfo val = null; if (!GameManager.TryFindPlayerByGuid(state.playerGuid, ref val)) { Plugin.Log.LogWarning((object)$"[Teams] Could not find player with guid={state.playerGuid}"); RestoreOriginalColors(entry); return; } if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)$"[Teams] Could not find player with guid={state.playerGuid}"); RestoreOriginalColors(entry); return; } PlayerTeam component = ((Component)val).GetComponent<PlayerTeam>(); if ((Object)(object)component == (Object)null || component.teamId < 0) { Plugin.Log.LogWarning((object)$"[Teams] Could not find player team for player with guid={state.playerGuid}"); RestoreOriginalColors(entry); return; } if ((Object)(object)TeamManager.Instance == (Object)null) { Plugin.Log.LogWarning((object)"[Teams] TeamManager not initialised yet; cannot apply team colors."); RestoreOriginalColors(entry); return; } if (!TeamManager.Instance.TryGetTeam(component.teamId, out TeamData team)) { Plugin.Log.LogWarning((object)$"[Teams] Could not find team with id={component.teamId}"); RestoreOriginalColors(entry); return; } Color color = team.Color; Color background = OriginalColors[entry].background; ((Graphic)entry.background).color = Color.Lerp(background, color, 0.5f); ((Graphic)entry.statusBackground).color = color; ((Graphic)entry.infoBackground).color = color; Color color2 = color; color2.a *= 0.5f; ((Graphic)entry.statsBackground).color = color2; Color stripes = OriginalColors[entry].stripes; Color color3 = Color.Lerp(stripes, color, 0.5f); color3.a = stripes.a; ((Graphic)entry.stripes).color = color3; Plugin.Log.LogInfo((object)("[Teams] Applied team color to " + ((Object)val).name)); } private static void RestoreOriginalColors(ScoreboardEntry entry) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0054: 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) if (OriginalColors.TryGetValue(entry, out ColorCache value)) { ((Graphic)entry.background).color = value.background; ((Graphic)entry.statusBackground).color = value.statusBackground; ((Graphic)entry.infoBackground).color = value.infoBackground; ((Graphic)entry.statsBackground).color = value.statsBackground; ((Graphic)entry.stripes).color = value.stripes; } } } public class TeeOffCountdownPatches { [HarmonyPatch(typeof(TeeOffCountdown), "Hide")] [HarmonyPostfix] public static void Hide_Postfix(TeeOffCountdown __instance) { MatchEvents.InvokeOnTeeOffFinished(); } } } namespace Gamemode_Lib.Patches.Features { public class DisableLevelBounds { [HarmonyPatch(typeof(LevelBoundsTracker), "Awake")] [HarmonyPostfix] public static void Awake_Prefix(LevelBoundsTracker __instance) { HideLevelBoundsObject(); } [HarmonyPatch(typeof(LevelBoundsTracker), "InformLevelBoundsStateChanged")] [HarmonyPrefix] public static void InformLevelBoundsStateChanged_Prefix(ref BoundsState boundsState) { bool flag = BoundsStateExtensions.HasState(boundsState, (BoundsState)1) || BoundsStateExtensions.HasState(boundsState, (BoundsState)2) || BoundsStateExtensions.HasState(boundsState, (BoundsState)4); if (BoundsStateExtensions.HasState(boundsState, (BoundsState)8) && !flag) { boundsState = (BoundsState)0; } } private static void HideLevelBoundsObject() { GameObject val = GameObject.Find("Level bounds"); if (!((Object)(object)val == (Object)null)) { MeshRenderer component = val.GetComponent<MeshRenderer>(); if (!((Object)(object)component == (Object)null)) { ((Renderer)component).forceRenderingOff = true; } } } } public class HideAheadOfBallMessage { [HarmonyPatch(typeof(AheadOfBallMessage), "Update")] [HarmonyPrefix] public static void Update_Prefix(AheadOfBallMessage __instance) { if (SingletonBehaviour<RestartPrompt>.HasInstance) { RestartPrompt instance = SingletonBehaviour<RestartPrompt>.Instance; Object.Destroy((Object)(object)instance); } __instance.HideInternal(); } } public class StopAutoNextHole { [CompilerGenerated] private static class <>O { public static UnityAction <0>__OnNextClicked; } [CompilerGenerated] private sealed class <FixLayoutNextFrame>d__4 : IAsyncStateMachine { public int <>1__state; public AsyncUniTaskMethodBuilder <>t__builder; public RectTransform rect; private Awaiter <>u__1; private void MoveNext() { //IL_004b: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0030: 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) int num = <>1__state; try { Awaiter awaiter; if (num != 0) { YieldAwaitable val = UniTask.Yield(); awaiter = ((YieldAwaitable)(ref val)).GetAwaiter(); if (!((Awaiter)(ref awaiter)).IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter; <FixLayoutNextFrame>d__4 <FixLayoutNextFrame>d__ = this; ((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter, <FixLayoutNextFrame>d__4>(ref awaiter, ref <FixLayoutNextFrame>d__); return; } } else { awaiter = <>u__1; <>u__1 = default(Awaiter); num = (<>1__state = -1); } ((Awaiter)(ref awaiter)).GetResult(); if (!((Object)(object)rect == (Object)null)) { LayoutRebuilder.ForceRebuildLayoutImmediate(rect); Canvas.ForceUpdateCanvases(); } } catch (Exception exception) { <>1__state = -2; ((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetException(exception); return; } <>1__state = -2; ((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetResult(); } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } } private static GameObject nextButtonInstance; public static bool END_GAME; [HarmonyPatch(typeof(CourseManager), "OnMatchStateChanged")] [HarmonyPrefix] public static bool OnMatchStateChanged_Prefix(CourseManager __instance, ref MatchState currentState) { if ((int)currentState == 6) { currentState = (MatchState)4; ServerInitiateMatchFinish(__instance); CreateNextButton(); return false; } return true; } public static void CreateNextButton() { //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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Expected O, but got Unknown if (!NetworkServer.active || !NetworkClient.active || (Object)(object)nextButtonInstance != (Object)null) { return; } GameObject val = ((IEnumerable<GameObject>)Resources.FindObjectsOfTypeAll<GameObject>()).FirstOrDefault((Func<GameObject, bool>)((GameObject o) => ((Object)o).name == "Message Button")); if ((Object)(object)val == (Object)null) { Debug.LogError((object)"Message Button not found!"); return; } Canvas val2 = ((IEnumerable<Canvas>)Object.FindObjectsOfType<Canvas>()).FirstOrDefault((Func<Canvas, bool>)((Canvas c) => ((Behaviour)c).isActiveAndEnabled && (int)c.renderMode != 2)); if ((Object)(object)val2 == (Object)null) { Debug.LogError((object)"Canvas not found!"); return; } nextButtonInstance = Object.Instantiate<GameObject>(val); ((Object)nextButtonInstance).name = "Next Button"; nextButtonInstance.transform.SetParent(((Component)val2).transform, false); RectTransform component = nextButtonInstance.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0f); component.anchorMax = new Vector2(0.5f, 0f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(0f, 120f); ((Transform)component).localScale = Vector3.one; component.sizeDelta = val.GetComponent<RectTransform>().sizeDelta; nextButtonInstance.SetActive(true); CanvasGroup[] componentsInChildren = nextButtonInstance.GetComponentsInChildren<CanvasGroup>(true); foreach (CanvasGroup val3 in componentsInChildren) { val3.alpha = 1f; val3.interactable = true; val3.blocksRaycasts = true; } Graphic[] componentsInChildren2 = nextButtonInstance.GetComponentsInChildren<Graphic>(true); foreach (Graphic val4 in componentsInChildren2) { ((Behaviour)val4).enabled = true; } TextMeshProUGUI componentInChildren = nextButtonInstance.GetComponentInChildren<TextMeshProUGUI>(true); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = "Next"; ((TMP_Text)componentInChildren).enableWordWrapping = false; ((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514; } Button component2 = nextButtonInstance.GetComponent<Button>(); if ((Object)(object)component2 != (Object)null) { ((UnityEventBase)component2.onClick).RemoveAllListeners(); ButtonClickedEvent onClick = component2.onClick; object obj = <>O.<0>__OnNextClicked; if (obj == null) { UnityAction val5 = OnNextClicked; <>O.<0>__OnNextClicked = val5; obj = (object)val5; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } UniTaskExtensions.Forget(FixLayoutNextFrame(component)); ShowCursor(); } [AsyncStateMachine(typeof(<FixLayoutNextFrame>d__4))] [DebuggerStepThrough] private static UniTask FixLayoutNextFrame(RectTransform rect) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) <FixLayoutNextFrame>d__4 <FixLayoutNextFrame>d__ = new <FixLayoutNextFrame>d__4(); <FixLayoutNextFrame>d__.<>t__builder = AsyncUniTaskMethodBuilder.Create(); <FixLayoutNextFrame>d__.rect = rect; <FixLayoutNextFrame>d__.<>1__state = -1; ((AsyncUniTaskMethodBuilder)(ref <FixLayoutNextFrame>d__.<>t__builder)).Start<<FixLayoutNextFrame>d__4>(ref <FixLayoutNextFrame>d__); return ((AsyncUniTaskMethodBuilder)(ref <FixLayoutNextFrame>d__.<>t__builder)).Task; } private static void ShowCursor() { CursorManager.SetCursorForceUnlocked(true); } public static void HideCursor() { CursorManager.SetCursorForceUnlocked(false); CursorManager.ApplyCursorLock(); } private static void OnNextClicked() { HideCursor(); CourseManager instance = SingletonNetworkBehaviour<CourseManager>.Instance; if (!((Object)(object)instance == (Object)null)) { if ((Object)(object)nextButtonInstance != (Object)null) { Object.Destroy((Object)(object)nextButtonInstance); nextButtonInstance = null; } if (!END_GAME) { SingletonNetworkBehaviour<CourseManager>.Instance.ServerStartNextMatch(false); } else { CourseManager.EndCourse(); } } } private static void ServerInitiateMatchFinish(CourseManager courseManager) { ServerFinishMatchDelayed(courseManager, isCourseFinished: false); } private static void AwardCourseBonus(CourseManager courseManager) { AwardCourseBonusAsync(courseManager); } private static async void ServerFinishMatchDelayed(CourseManager courseManager, bool isCourseFinished) { if (!MatchSetupRules.IsCheatsEnabled() && isCourseFinished) { AwardCourseBonus(courseManager); } NextMatchCountdown.Show(); ((TMP_Text)SingletonNetworkBehaviour<NextMatchCountdown>.Instance.message).SetText("Waiting for host!"); float delayDuration = (isCourseFinished ? GameManager.MatchSettings.FinishCourseDelay : GameManager.MatchSettings.StartNextMatchDelay); for (float time = 0f; time < delayDuration; time += Time.deltaTime) { if (!courseManager.forceDisplayScoreboard && time >= GameManager.MatchSettings.MatchEndScoreboardDisplayDelay) { courseManager.NetworkforceDisplayScoreboard = true; } await UniTask.Yield(); if ((Object)(object)courseManager == (Object)null) { return; } } if (isCourseFinished) { courseManager.EndCourseInternal(); } } private static async void AwardCourseBonusAsync(CourseManager courseManager) { await UniTask.WaitForSeconds(1f, false, (PlayerLoopTiming)8, default(CancellationToken), false); if ((Object)(object)courseManager == (Object)null) { return; } List<PlayerState> playerStatesInternal = courseManager.GetSortedPlayerStatesInternal(false); if (playerStatesInternal.Count <= 1) { return; } List<PlayerState> list = default(List<PlayerState>); PooledObject<List<PlayerState>> val = CollectionPool<List<PlayerState>, PlayerState>.Get(ref list); try { NetworkConnectionToClient connection = default(NetworkConnectionToClient); for (int i = 0; i < playerStatesInternal.Count; i++) { PlayerState playerState = playerStatesInternal[i]; if (playerState.isConnected && !playerState.isSpectator && BNetworkManager.singleton.ServerTryGetConnectionFromPlayerGuid(playerState.playerGuid, ref connection)) { float awardMultiplier = ((i == 0) ? 1f : ((i >= playerStatesInternal.Count / 2) ? 0.5f : 0.75f)); courseManager.RpcAwardCourseBonus(connection, awardMultiplier); } connection = null; } } finally { ((IDisposable)val).Dispose(); } } } public class StopCountdownToMatchEnd { [HarmonyPatch(typeof(CourseManager), "BeginCountdownToMatchEnd")] [HarmonyPrefix] public static bool BeginCountdownToMatchEnd_Postfix(CourseManager __instance) { return false; } } } namespace Gamemode_Lib.Teams { public struct GamemodeEndMessage : NetworkMessage { public string GamemodeId; } public struct GamemodeStartMessage : NetworkMessage { public string GamemodeId; } public struct TeamAssignMessage : NetworkMessage { public ulong PlayerGuid; public int TeamId; } public struct TeamDefinitionMessage : NetworkMessage { public int ID; public Color Color; public string Name; } public class PlayerTag : MonoBehaviour { public enum TagHitType { Dive, GolfSwing } private Hittable hittable; private PlayerTeam playerTeam; public static event Action<PlayerInfo, PlayerInfo, TagHitType> PlayerTagged; private void Awake() { hittable = ((Component)this).GetComponent<Hittable>(); playerTeam = ((Component)this).GetComponent<PlayerTeam>(); if ((Object)(object)hittable != (Object)null) { hittable.WasHitByDive += OnWasHitByDive; hittable.WasHitByGolfSwing += OnWasHitByGolfSwing; } } private void OnDestroy() { if ((Object)(object)hittable != (Object)null) { hittable.WasHitByDive -= OnWasHitByDive; hittable.WasHitByGolfSwing -= OnWasHitByGolfSwing; } } public void OnWasHitByDive(PlayerMovement hitter) { if ((GameModeUtilities.CurrentGamemodeId == null || GameModeUtilities.Modes[GameModeUtilities.CurrentGamemodeId].IsTaggingEnabled) && !((Object)(object)hittable == (Object)null)) { PlayerInfo val = (PlayerInfo)(((Object)(object)playerTeam != (Object)null) ? ((object)playerTeam.playerInfo) : ((object)((Component)this).GetComponent<PlayerInfo>())); PlayerInfo val2 = (((Object)(object)hitter != (Object)null) ? ((Component)hitter).GetComponent<PlayerInfo>() : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val == (Object)null)) { Plugin.Log.LogInfo((object)("Player " + (((val != null) ? ((Object)((Component)val).gameObject).name : null) ?? ((Object)((Component)this).gameObject).name) + " was hit by dive from " + (((val2 != null) ? ((Object)((Component)val2).gameObject).name : null) ?? ((hitter != null) ? ((Object)((Component)hitter).gameObject).name : null) ?? "unknown"))); PlayerTag.PlayerTagged?.Invoke(val, val2, TagHitType.Dive); } } } public void OnWasHitByGolfSwing(PlayerGolfer hitter, Vector3 vector3, float arg3, bool arg4) { if ((GameModeUtilities.CurrentGamemodeId == null || GameModeUtilities.Modes[GameModeUtilities.CurrentGamemodeId].IsTaggingEnabled) && !((Object)(object)hittable == (Object)null)) { PlayerInfo val = (PlayerInfo)(((Object)(object)playerTeam != (Object)null) ? ((object)playerTeam.playerInfo) : ((object)((Component)this).GetComponent<PlayerInfo>())); PlayerInfo val2 = (((Object)(object)hitter != (Object)null) ? ((Component)hitter).GetComponent<PlayerInfo>() : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val == (Object)null)) { Plugin.Log.LogInfo((object)("Player " + (((val != null) ? ((Object)((Component)val).gameObject).name : null) ?? ((Object)((Component)this).gameObject).name) + " was hit by swing from " + (((val2 != null) ? ((Object)((Component)val2).gameObject).name : null) ?? ((hitter != null) ? ((Object)((Component)hitter).gameObject).name : null) ?? "unknown"))); PlayerTag.PlayerTagged?.Invoke(val, val2, TagHitType.GolfSwing); } } } } public class PlayerTeam : MonoBehaviour { public int teamId = -1; public PlayerInfo playerInfo; private void Awake() { ((Component)this).gameObject.AddComponent<PlayerTag>(); playerInfo = ((Component)this).GetComponent<PlayerInfo>(); if ((Object)(object)TeamManager.Instance != (Object)null) { TeamManager.Instance.RegisterPlayer(this); } } public void SetLocalTeam(int newTeam) { int num = teamId; teamId = newTeam; Plugin.Log.LogInfo((object)$"[LOCAL] Team changed {num} -> {newTeam}"); TeamManager.Instance?.NotifyTeamChanged(this, num, newTeam); } private void OnDestroy() { TeamManager.Instance?.UnregisterPlayer(this); } } public class TeamData { public int ID; public Color Color; public string Name; public int Score; public readonly HashSet<PlayerTeam> Members = new HashSet<PlayerTeam>(); public int MemberCount => Members.Count; internal void AddMember(PlayerTeam player) { if (!((Object)(object)player == (Object)null)) { Members.Add(player); } } internal void RemoveMember(PlayerTeam player) { if (!((Object)(object)player == (Object)null)) { Members.Remove(player); } } internal void ClearMembers() { Members.Clear(); } } public class TeamManager : MonoBehaviour { private readonly struct BroadcastSuppressScope : IDisposable { private readonly TeamManager _manager; public BroadcastSuppressScope(TeamManager manager) { _manager = manager; _manager._broadcastSuppressDepth++; } public void Dispose() { _manager._broadcastSuppressDepth = Mathf.Max(0, _manager._broadcastSuppressDepth - 1); } } [CompilerGenerated] private sealed class <PlayerTeamsInScene>d__43 : IEnumerable<PlayerTeam>, IEnumerable, IEnumerator<PlayerTeam>, IEnumerator, IDisposable { private int <>1__state; private PlayerTeam <>2__current; private int <>l__initialThreadId; public TeamManager <>4__this; private PlayerInfo[] <>s__1; private int <>s__2; private PlayerInfo <info>5__3; private PlayerTeam <team>5__4; PlayerTeam IEnumerator<PlayerTeam>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayerTeamsInScene>d__43(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>s__1 = null; <info>5__3 = null; <team>5__4 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_008d; } <>1__state = -1; <>s__1 = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0); <>s__2 = 0; goto IL_00aa; IL_008d: <team>5__4 = null; <info>5__3 = null; <>s__2++; goto IL_00aa; IL_00aa: if (<>s__2 < <>s__1.Length) { <info>5__3 = <>s__1[<>s__2]; <team>5__4 = <>4__this.EnsurePlayerTeam(<info>5__3); if ((Object)(object)<team>5__4 != (Object)null) { <>2__current = <team>5__4; <>1__state = 1; return true; } goto IL_008d; } <>s__1 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<PlayerTeam> IEnumerable<PlayerTeam>.GetEnumerator() { <PlayerTeamsInScene>d__43 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <PlayerTeamsInScene>d__43(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<PlayerTeam>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <RequestTeamFromHostCoroutine>d__29 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerInfo info; public int instanceId; public TeamManager <>4__this; private int <i>5__1; private ulong <guid>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RequestTeamFromHostCoroutine>d__29(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <>1__state = -3; <i>5__1 = 0; break; case 1: <>1__state = -3; <i>5__1++; break; } if (<i>5__1 < 300) { if ((Object)(object)info == (Object)null) { result = false; goto IL_011f; } <guid>5__2 = info.PlayerId.guid; if (<guid>5__2 != 0) { NetworkMessageBootstrap.Register(); TeamRequestMessage teamRequestMessage = default(TeamRequestMessage); teamRequestMessage.PlayerGuid = <guid>5__2; NetworkClient.Send<TeamRequestMessage>(teamRequestMessage, 0); Plugin.Log.LogInfo((object)$"[Teams] Requested team for local player guid={<guid>5__2}"); result = false; goto IL_011f; } <>2__current = null; <>1__state = 1; result = true; } else { Plugin.Log.LogWarning((object)"[Teams] Timed out waiting for local player guid; team request not sent."); <>m__Finally1(); result = false; } goto end_IL_0000; IL_011f: <>m__Finally1(); end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; <>4__this._requestedTeamInstanceIds.Remove(instanceId); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ValidPlayers>d__41 : IEnumerable<PlayerTeam>, IEnumerable, IEnumerator<PlayerTeam>, IEnumerator, IDisposable { private int <>1__state; private PlayerTeam <>2__current; private int <>l__initialThreadId; public TeamManager <>4__this; private HashSet<PlayerTeam>.Enumerator <>s__1; private PlayerTeam <player>5__2; PlayerTeam IEnumerator<PlayerTeam>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ValidPlayers>d__41(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = default(HashSet<PlayerTeam>.Enumerator); <player>5__2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.Players.RemoveWhere((PlayerTeam player) => (Object)(object)player == (Object)null); <>s__1 = <>4__this.Players.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <player>5__2 = null; break; } if (<>s__1.MoveNext()) { <player>5__2 = <>s__1.Current; <>2__current = <player>5__2; <>1__state = 1; return true; } <>m__Finally1(); <>s__1 = default(HashSet<PlayerTeam>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<PlayerTeam> IEnumerable<PlayerTeam>.GetEnumerator() { <ValidPlayers>d__41 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <ValidPlayers>d__41(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<PlayerTeam>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <ValidPlayersWithInfo>d__42 : IEnumerable<(PlayerTeam Player, PlayerInfo Info)>, IEnumerable, IEnumerator<(PlayerTeam Player, PlayerInfo Info)>, IEnumerator, IDisposable { private int <>1__state; private (PlayerTeam Player, PlayerInfo Info) <>2__current; private int <>l__initialThreadId; public TeamManager <>4__this; private IEnumerator<PlayerTeam> <>s__1; private PlayerTeam <player>5__2; (PlayerTeam, PlayerInfo) IEnumerator<(PlayerTeam, PlayerInfo)>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ValidPlayersWithInfo>d__42(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = null; <player>5__2 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; goto IL_009c; } <>1__state = -1; <>s__1 = <>4__this.ValidPlayers().GetEnumerator(); <>1__state = -3; goto IL_00a4; IL_009c: <player>5__2 = null; goto IL_00a4; IL_00a4: if (<>s__1.MoveNext()) { <player>5__2 = <>s__1.Current; if ((Object)(object)<player>5__2.playerInfo != (Object)null) { <>2__current = (<player>5__2, <player>5__2.playerInfo); <>1__state = 1; return true; } goto IL_009c; } <>m__Finally1(); <>s__1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__1 != null) { <>s__1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<(PlayerTeam Player, PlayerInfo Info)> IEnumerable<(PlayerTeam, PlayerInfo)>.GetEnumerator() { <ValidPlayersWithInfo>d__42 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <ValidPlayersWithInfo>d__42(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<(PlayerTeam, PlayerInfo)>)this).GetEnumerator(); } } public static TeamManager Instance; public readonly Dictionary<int, TeamData> Teams = new Dictionary<int, TeamData>(); public readonly HashSet<PlayerTeam> Players = new HashSet<PlayerTeam>(); public readonly Dictionary<ulong, int> SavedTeamIdByGuid = new Dictionary<ulong, int>(); public PlayerTeam LocalPlayerTeam; private readonly Dictionary<ulong, int> _pendingTeamIdByGuid = new Dictionary<ulong, int>(); private readonly HashSet<int> _requestedTeamInstanceIds = new HashSet<int>(); private int _broadcastSuppressDepth; private int? _lastAllPlayersOnOneTeamId; private bool IsBroadcastSuppressed => _broadcastSuppressDepth > 0; public event Action<TeamData> AllPlayersOnOneTeam; private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)this); return; } Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); foreach (PlayerTeam item in PlayerTeamsInScene()) { } } public void RegisterPlayer(PlayerTeam player) { if (!((Object)(object)player == (Object)null)) { Players.Add(player); if (player.teamId >= 0) { EnsureTeamData(player.teamId)?.AddMember(player); } EvaluateAllPlayersOnOneTeam(); } } public void UnregisterPlayer(PlayerTeam player) { if ((Object)(object)player == (Object)null) { return; } Players.Remove(player); foreach (TeamData value in Teams.Values) { value?.RemoveMember(player); } EvaluateAllPlayersOnOneTeam(); } public PlayerTeam EnsurePlayerTeam(PlayerInfo info) { if ((Object)(object)info == (Object)null) { return null; } PlayerTeam playerTeam = default(PlayerTeam); if (!((Component)info).TryGetComponent<PlayerTeam>(ref playerTeam) || (Object)(object)playerTeam == (Object)null) { playerTeam = ((Component)info).gameObject.AddComponent<PlayerTeam>(); } playerTeam.playerInfo = info; RegisterPlayer(playerTeam); if ((Object)(object)SingletonBehaviour<GameManager>.Instance?.localPlayerInfo == (Object)(object)info) { LocalPlayerTeam = playerTeam; } ApplyPendingTeamIfAny(info, playerTeam); return playerTeam; } public bool TryRefreshLocalPlayerTeam() { LocalPlayerTeam = EnsurePlayerTeam(SingletonBehaviour<GameManager>.Instance?.localPlayerInfo); return (Object)(object)LocalPlayerTeam != (Object)null; } public void SetTeam(PlayerTeam player, int teamId, bool broadcastToClients = true) { if ((Object)(object)player == (Object)null) { return; } if (broadcastToClients) { player.SetLocalTeam(teamId); return; } using (SuppressBroadcast()) { player.SetLocalTeam(teamId); } } internal void NotifyTeamChanged(PlayerTeam player, int oldTeamId, int newTeamId) { MoveMember(player, oldTeamId, newTeamId); if (NetworkServer.active && TryGetGuid(player, out var guid)) { SaveTeamId(guid, newTeamId); Plugin.Log.LogInfo((object)$"[Teams] Persisted team change guid={guid}: {oldTeamId} -> {newTeamId}"); if (!IsBroadcastSuppressed) { BroadcastTeam(guid, newTeamId); } } EvaluateAllPlayersOnOneTeam(); } public void AssignUnAssignedPlayersToTeams(bool broadcastToClients = true) { if (!NetworkServer.active || Teams.Count <= 0) { return; } int num = 0; foreach (PlayerTeam item in ValidPlayers()) { if (item.teamId == -1) { SetTeam(item, num % Teams.Count, broadcastToClients); num++; } } } public void CreateAndAssignTeams(int teamCount) { if (!NetworkServer.active || teamCount <= 0) { return; } Teams.Clear(); for (int i = 0; i < teamCount; i++) { SendTeamDefinitionToClients(EnsureTeamData(i)); } int num = 0; foreach (PlayerTeam item in PlayerTeamsInScene()) { SetTeam(item, num % teamCount); num++; } } public void ResetTeams() { if (!NetworkServer.active) { return; } foreach (PlayerTeam item in PlayerTeamsInScene()) { SetTeam(item, -1); } } public void ResetToDefaults(bool broadcastToClients) { SavedTeamIdByGuid.Clear(); _pendingTeamIdByGuid.Clear(); _requestedTeamInstanceIds.Clear(); _lastAllPlayersOnOneTeamId = null; Teams.Clear(); foreach (PlayerTeam item in ValidPlayers()) { SetTeam(item, -1, broadcastToClients); } LocalPlayerTeam = null; TryRefreshLocalPlayerTeam(); EvaluateAllPlayersOnOneTeam(); } public void SaveCurrentTeams() { SavedTeamIdByGuid.Clear(); foreach (var (playerTeam, val) in ValidPlayersWithInfo()) { SaveTeamId(val.PlayerId.guid, playerTeam.teamId); } } public int ReloadSavedTeams(bool broadcastToClients = true) { int num = 0; foreach (var (player, val) in ValidPlayersWithInfo()) { if (SavedTeamIdByGuid.TryGetValue(val.PlayerId.guid, out var value)) { SetTeam(player, value, broadcastToClients); num++; } } return num; } public bool TryApplySavedTeam(PlayerInfo info, bool broadcastToClients = true) { if ((Object)(object)info == (Object)null) { return false; } if (!SavedTeamIdByGuid.TryGetValue(info.PlayerId.guid, out var value)) { return false; } SetTeam(EnsurePlayerTeam(info), value, broadcastToClients); return true; } public void RequestTeamFromHost(PlayerInfo info) { if (!((Object)(object)info == (Object)null) && NetworkClient.active && !NetworkServer.active && !((Object)(object)SingletonBehaviour